Блокировка потоков - PullRequest
       6

Блокировка потоков

2 голосов
/ 29 февраля 2012

G'day,

Я пытался провести простой многопоточный эксперимент, используя ruby ​​1.9.3.

Код:

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

Вызов

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>'

Что я делаю не так, здесь?Я перепробовал множество вещей, вызывая Thread#join вместо Thread#stop, вообще не вызывая метод Thread, когда я закончил и т. Д.

Заранее спасибо!


Пересмотренный код:

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

Ответы [ 4 ]

3 голосов
/ 29 февраля 2012

Не stop нить, пока она удерживает мьютекс. Метод stop переводит текущий поток в состояние ожидания и планирует другой поток. Теперь первый поток удерживает мьютекс, так что какой бы другой поток не был запланирован следующим, он ожидает, что остановленный поток освободит мьютекс, что никогда не произойдет. Тупик.

0 голосов
/ 23 июня 2017

Вы не можете сделать Thread.list.join, потому что этот список включает основной поток.

Если вы делаете Thread.main.join, это вызывает ошибку, потому что вы ждете себя, а это чепуха.

Вы можете сделать:

Thread.list.delete_if { |t| t == Thread.main }.map(&:join)
0 голосов
/ 01 марта 2012

Вы не можете использовать переменную t внутри потока. Попробуйте использовать Thread.stop, указывая текущий поток. Как в:

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

Также я не знаю, сможете ли вы присоединиться к остановленным темам. Почему бы тогда не активироваться перед присоединением?

Thread.list.each {|t| t.run; t.join }
puts res
0 голосов
/ 29 февраля 2012

@FranciscoP. Что бы вы ни определяли в цикле, оно остается локальным для цикла, вы назвали поток в цикле, он не будет доступен вне цикла, я думаю, вы должны определить переменную вне цикла и передать поток впеременная, тогда поток будет доступен для вас, когда цикл завершится.

например:

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 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...