如何在Ruby中的join()中修复死锁 [英] How to fix a deadlock in join() in Ruby

查看:96
本文介绍了如何在Ruby中的join()中修复死锁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Ruby中进行多线程处理. 该代码段为:

I am working in multi-threading in Ruby. The code snippet is:

  threads_array = Array.new(num_of_threads)  
  1.upto(num_of_threads) do |i|  

    Thread.abort_on_exception = true
      threads_array[i-1] =  Thread.new {
        catch(:exit) do
          print "s #{i}"
          user_id = nil
          loop do
            user_id = user_ids.pop()
            if user_id == nil
              print "a #{i}"
              Thread.stop()
            end
            dosomething(user_id)
          end
        end
      }
    end
    #puts "after thread"
    threads_array.each {|thread| thread.join}

我没有使用任何互斥锁,但是出现了死锁.这是上面的代码片段的输出:

I am not using any mutex locks, but I get a deadlock. This is the output of the above code snippet:

s 2s 6s 8s 1s 11s 7s 10s 14s 16s 21s 24s 5s 26s 3s 19s 20s 23s 4s 28s 9s 12s 18s 22s 29s 30s 27s 13s 17s 15s 25a 4a 10a 3a 6a 21a 24a 16a 9a 18a 5a 28a 20a 2a 22a 11a 29a 8a 14a 23a 26a 1a 19a 7a 12fatal: deadlock detected

上面的输出告诉我,死锁是在user_ids数组为null之后,并且在线程的joinstop中发生.

The above output tells me that the deadlock is after the user_ids array is null and happening with Thread's join and stop.

实际上正在发生什么,该错误的解决方法是什么?

What actually is happening and what is the solution to this error?

推荐答案

重现此问题的最简单代码是:

The simplest code to reproduce this issue is:

t = Thread.new { Thread.stop }
t.join # => exception in `join': deadlock detected (fatal)

线程::停止→无

停止当前线程的执行,使其进入休眠"状态 状态,并计划另一个线程的执行.

Stops execution of the current thread, putting it into a "sleep" state, and schedules execution of another thread.

线程#加入→thr
线程#join(限制)→thr

Thread#join → thr
Thread#join(limit) → thr

调用线程将暂停执行并运行thr.不退货 直到thr退出或直到限制秒数为止.如果有时间限制 过期,将返回nil,否则返回thr.

The calling thread will suspend execution and run thr. Does not return until thr exits or until limit seconds have passed. If the time limit expires, nil will be returned, otherwise thr is returned.

据我了解,您在线程上没有参数的情况下调用了Thread.join并等待其退出,但是子线程调用了Thread.stop并进入了sleep状态.这是一种死锁情况,主线程等待子线程退出,但是子线程正在休眠并且没有响应.

As far as I understand you call Thread.join without parameters on thread and wait for it to exit, but the child thread calls Thread.stop and goes into sleep status. This is a deadlock situation, the main thread waits for the child thread to exit, but the child thread is sleeping and not responding.

如果使用limit参数调用join,则子线程将在超时后中止而不会导致程序死锁:

If you call join with limit the parameter then the child thread will be aborted after a timeout without causing a deadlock to your program:

t = Thread.new { Thread.stop }
t.join 1 # => Process finished with exit code 0

我建议在使用Thread.exit完成工作线程后退出工作线程,或者摆脱无限循环并正常到达执行线程的末尾,例如:

I would recommend exiting your worker threads after they do the job with Thread.exit or get rid of the infinite loop and reach the end of the execution thread normally, for example:

if user_id == nil
  raise StopIteration
end

#or 
if user_id == nil
  Thread.exit
end

这篇关于如何在Ruby中的join()中修复死锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆