/ / Fils bloqués - rubis, multithreading, impasse

Fils bloqués - rubis, multithreading, impasse

G "jour,

J'essayais de faire une simple expérience multithreading utilisant Ruby 1.9.3.

Le code:

require "thread"

ary = *0..10

res = 0
mutex = Mutex.new
#cv = ConditionVariable.new

ary.each do |x|
p "Iteration no. #{x}"
t = Thread.new do
p "Thread taking care of #{x}"
mutex.synchronize do
#cv.wait(mutex)
res += x
t.stop
end
end
end

Thread.list.each do |t| t.join; end
puts res

L'appel

brode@curral:~/coding$ ruby --version
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-linux]
brode@curral:~/coding$ ruby mt.rb
"Iteration no. 0"
"Iteration no. 1"
"Iteration no. 2"
"Iteration no. 3"
"Iteration no. 4"
"Thread taking care of 2"
"Thread taking care of 1"
"Thread taking care of 0"
"Thread taking care of 3"
"Iteration no. 5"
"Thread taking care of 4"
"Iteration no. 6"
"Thread taking care of 5"
"Iteration no. 7"
"Thread taking care of 6"
"Iteration no. 8"
"Thread taking care of 7"
"Iteration no. 9"
"Thread taking care of 8"
"Iteration no. 10"
"Thread taking care of 9"
"Thread taking care of 10"
mt.rb:21:in `join": deadlock detected (fatal)
from mt.rb:21:in `block in <main>"
from mt.rb:21:in `each"
from mt.rb:21:in `<main>"

Qu'est-ce que je fais mal, ici? J’ai essayé plein de choses en appelant Thread#join au lieu de Thread#stop, ne pas appeler Thread méthode du tout quand je suis fait, etc.

Merci d'avance!


Code révisé:

require "thread"

ary = *0..10

res = 0
mutex = Mutex.new

ary.each do |x|
p "Iteration no. #{x}"
t = Thread.new do
p "Thread taking care of #{x}"
mutex.synchronize do
res += x
end
t.stop
end
end

Thread.list.each &:join
puts res

Réponses:

2 pour la réponse № 1

Ne pas stop un fil pendant qu'il tient un mutex. le stop méthode met le fil actuel dans un sommeilEtat et programme un autre thread. À présent, le premier thread contient le mutex, de sorte que le prochain thread programmé finisse par attendre que le thread arrêté libère le mutex, ce qui ne se produira jamais. Impasse.


0 pour la réponse № 2

@FranciscoP.tout ce que vous définissez dans une boucle reste local à la boucle, vous avez appelé le fil dans la boucle il ne serait pas disponible en dehors de la boucle, je pense que vous devriez définir une variable en dehors de la boucle et passer le fil à la variable, puis le fil serait disponible pour vous lorsque la boucle est terminée.

par exemple:

threads = []

threads << Thread.new do
ary.each do |x|
p "Iteration no. #{x}"
mutex.synchronize do
res += x
end
end
threads.each { |t| t.join }

0 pour la réponse № 3

Vous ne pouvez pas "utiliser la variable t à l'intérieur du thread. Essayez d'utiliser Thread.stop, en indiquant le thread actuel. Comme dans:

require "thread"

ary = *0..10

res = 0
mutex = Mutex.new

ary.each do |x|
p "Iteration no. #{x}"
t = Thread.new do
p "Thread taking care of #{x}"
mutex.synchronize do
res += x
end
Thread.stop
end
end

Thread.list.each &:join
puts res

De plus, je ne sais pas si vous pourrez rejoindre les threads arrêtés. Pourquoi ne pas réactiver avant la jointure?

Thread.list.each {|t| t.run; t.join }
puts res

0 pour la réponse № 4

Vous ne pouvez pas faire Thread.list.join car cette liste inclut le fil principal.

Si vous faites Thread.main.join cela soulève une erreur parce que vous vous attendez et que c'est un non-sens

Vous pourriez faire:

Thread.list.delete_if { |t| t == Thread.main }.map(&:join)