ruby - 使用 SizedQueue 在 ruby​​ 代码中出现死锁

标签 ruby multithreading queue deadlock

我认为我对线程在 ruby​​ 中的工作原理存在根本性的误解,我希望获得一些见解。

我想要一个简单的生产者和消费者。首先,生产者线程从文件中提取行并将它们粘贴到 SizedQueue 中;当那些用完时,在末端贴上一些 token ,让消费者知道事情已经完成。

require 'thread'
numthreads = 2
filename = 'edition-2009-09-11.txt'

bq = SizedQueue.new(4)
producerthread = Thread.new(bq) do |queue|
  File.open(filename) do |f|
    f.each  do |r|
      queue << r
    end
  end
  numthreads.times do
    queue << :end_of_producer
  end
end

现在有几个消费者。为简单起见,让他们什么都不做。

consumerthreads = []

numthreads.times do
  consumerthreads << Thread.new(bq) do |queue|
    until (line = queue.pop) === :end_of_producer
       # do stuff in here
    end
  end
end

producerthread.join
consumerthreads.each {|t| t.join}

puts "All done"

我的理解是 (a) 一旦 SizedQueue 已满,生产者线程将阻塞并最终返回填充它,并且 (b) 消费者线程将从 SizedQueue 中拉出,在它清空时阻塞,并最终完成.

但是在 ruby​​1.9(ruby 1.9.1p243(2009-07-16 修订版 24175)[i386-darwin9])下,我在连接上遇到死锁错误。这里发生了什么?除了 SizedQueue,我只是看不到线程之间的任何交互,它应该是线程安全的。

如有任何见解,我们将不胜感激。

最佳答案

你的理解是正确的,你的代码可以在我的机器上运行,在稍微更新的 Ruby 版本(ruby 1.9.2dev (2009-08-30 trunk 24705) [i386-darwin10.0.0] 和 ruby​​ 1.9.2dev ( 2009-08-30 主干 24705) [i386-darwin10.0.0])

关于ruby - 使用 SizedQueue 在 ruby​​ 代码中出现死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2414905/

相关文章:

ruby - 以编程方式设置 GEM_HOME/PATH 或 Gem.path

ruby-on-rails - 正确使用 `rescue`(或 `try`)

java - Android Intent打开新 Activity 但没有关闭旧 Activity

java - 如何获取线程引用以在 contextDestroyed 方法中停止它

c# - 多线程.NET队列问题

c++ - 如何显示我的队列和堆栈?

ruby - 如何在 <br> 之后使用 Mechanize 提取文本

java - 在绘画中使用thread.sleep方法

ruby-on-rails - Resque .. 我怎样才能得到队列列表

ruby - 如何 stub 在 RSpec 中接受多个参数的基类方法?