2010-03-10 16 views
5

Creo que me estoy enfrentando a un malentendido fundamental de cómo funciona el subprocesamiento en ruby ​​y espero obtener alguna información.Interbloqueo en código de ruby ​​con SizedQueue

Me gustaría tener un simple productor y consumidor. Primero, un hilo productor que extrae líneas de un archivo y las pega en un SizedQueue; cuando se agoten, pegue algunos tokens al final para que los consumidores sepan que las cosas están hechas.

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 

Ahora algunos consumidores. Para simplificar, hagamos que no hagan nada.

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" 

Mi entendimiento es que (a) el hilo productor bloqueará una vez que el SizedQueue está lleno y, finalmente, volver a llenarlo, y (b) los hilos de consumo se tire de la SizedQueue, bloqueo cuando se vacía y eventualmente terminar

Pero bajo ruby1.9 (ruby 1.9.1p243 (2009-07-16 revisión 24175) [i386-darwin9]) Obtengo un error de interbloqueo en las uniones. ¿Que está pasando aqui? Simplemente no veo dónde hay interacción entre los hilos, excepto a través de SizedQueue, que se supone que es seguro para subprocesos.

Cualquier idea sería muy apreciada.

Respuesta

3

Tu comprensión es correcta y tu código funciona en mi máquina, en una versión ligeramente más nueva de Ruby (tanto ruby ​​1.9.2dev (2009-08-30 trunk 24705) [i386-darwin10.0.0] como ruby ​​1.9.2dev (2009-08-30 trunk 24705) [i386-darwin10.0.0])

+0

Excelente. Verificado que funciona con un tronco 1.9 reciente. ¡Gracias! –

+0

No hay problema. Entonces debe "aceptar" la respuesta haciendo clic en la marca de verificación. –