Я думаю, что столкнулся с фундаментальным недоразумением с моей стороны о том, как работает многопоточность в ruby, и я надеюсь получить некоторое представление.
Я бы хотел иметь простого производителя и потребителя. Во-первых, поток производителя, который извлекает строки из файла и вставляет их в SizedQueue; когда они закончатся, прикрепите несколько жетонов на конце, чтобы потребитель (и) знал, что все сделано.
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"
Насколько я понимаю, (а) поток-производитель заблокирует, как только SizedQueue заполнится, и в конечном итоге вернется к его заполнению, и (b) потребительские потоки будут извлекать из SizedQueue, блокируя, когда он опустошается, и в конце концов заканчивать .
Но в ruby1.9 (ruby 1.9.1p243 (2009-07-16 ревизия 24175) [i386-darwin9]) я получаю ошибку взаимоблокировки соединений. Что тут происходит? Я просто не вижу, где есть взаимодействие между потоками, кроме как через SizedQueue, который должен быть потокобезопасным.
Любое понимание будет высоко ценится.