2012-01-19 21 views
5

मैं रूबी में बहु थ्रेडिंग में काम कर रहा हूं।डेडलॉक शामिल हों()

threads_array = Array.new(num_of_threads) 
    1.upto(num_of_threads) do |i| 

    Thread.abort_on_exception = true 
     threads_array[i-1] = Thread.new { 
     catch(:exit) do 
      print "s #{i}" 
      user_id = nil 
      loop do 
      user_id = user_ids.pop() 
      if user_id == nil 
       print "a #{i}" 
       Thread.stop() 
      end 
      dosomething(user_id) 
      end 
     end 
     } 
    end 
    #puts "after thread" 
    threads_array.each {|thread| thread.join} 

मैं किसी भी म्युटेक्स ताले उपयोग नहीं कर रहा कोड स्निपेट है। लेकिन मैं गतिरोध मिल .. के बाद से ऊपर कोड स्निपेट के उत्पादन में है ..

रों 2s 6s 8s 1s 11s 7s 10s 14s -16 -21 24s 5s 26s 3s 19s 20s 23s 4s 28s 9 नंबर के पत्तों 12s 18s 22s 29s 30s 27s 13s 17s 15s 25A 4a 10A 3a 6a 21A 24a 16A 9a 18a 5a 28a 20a 2a 22a 11A 29a 8a 14A 23a 26a 1a 19A 7a 12fatal: गतिरोध का पता चला

ऊपर उत्पादन हमें बताता है के बाद user_ids सरणी रिक्त है और कहा कि गतिरोध है रूबी में थ्रेड क्लास के शामिल() और स्टॉप() के साथ हो रहा है .. वास्तव में क्या हो रहा है और इस त्रुटि का समाधान क्या है ??

+0

मेरा उत्तर सहायक था? क्या आपने इस मुद्दे को हल किया है? –

उत्तर

19

इस समस्या को ठीक करने साधारण कोड है:

t = Thread.new { Thread.stop } 
t.join # => exception in `join': deadlock detected (fatal) 

थ्रेड :: रोक → शून्य

बंद हो जाता है वर्तमान धागे के निष्पादन, यह एक "नींद" में डाल राज्य , और एक और धागे के निष्पादन शेड्यूल।

थ्रेड # में शामिल होने → thr
थ्रेड # (सीमा) → thr

बुला धागे निष्पादन को निरस्त करने और thr चलेंगे में शामिल हो। वापस नहीं निकलता है जब तक कि थ्रेट एक्स्टिट या सीमा सेकंड पास नहीं हो जाते। यदि समय सीमा की समय सीमा समाप्त हो जाती है, तो शून्य वापस कर दिया जाएगा, अन्यथा वापस लौटा दिया जाएगा।

जहां तक ​​मैं समझता हूँ कि आप धागे पर पैरामीटर के बिना Thread.join फोन और इसे बाहर निकलने के लिए के लिए इंतजार है, लेकिन बच्चे धागा Thread.stop कॉल और sleep स्थिति में चला जाता है। यह एक डेडलोक स्थिति है - मुख्य धागा बाल धागे से बाहर निकलने के लिए प्रतीक्षा करें, लेकिन बाल धागा सो रहा है और जवाब नहीं दे रहा है।

यदि आप फोन joinlimit साथ पैरामीटर उसके बाद बच्चे धागा अपने कार्यक्रम के लिए गतिरोध पैदा करने के बिना समय समाप्ति के बाद निरस्त कर दिया जाएगा:

t = Thread.new { Thread.stop } 
t.join 1 # => Process finished with exit code 0 

मैं अपने कार्यकर्ता धागे बाहर निकलने के लिए सलाह देते हैं के बाद वे Thread.exit या पाने के साथ काम किया है होगा अनंत लूप से छुटकारा और सामान्य रूप से निष्पादन धागा के अंत तक पहुँचते उदाहरण के लिए,:

if user_id == nil 
    raise StopIteration 
end 

#or 
if user_id == nil 
    Thread.exit 
end 
+0

अच्छा लेखन-अप; बहुत बढ़िया। – Phrogz

+0

कमाल, धन्यवाद – glebm

0

अगर मैं अपने इरादों मिल सही मैं कुछ सरल (और शायद सुरक्षित,पर विचार करेंगेधागा भीतर से मेरे लिए डरावना लग रहा है):

user_ids = (0..19).to_a 
number_of_threads = 3 

user_ids \ 
    .each_slice(user_ids.length/number_of_threads + 1) \ 
    .map { |slice| 
     Thread.new(slice) { |s| 
     puts s.inspect 
     } 
    }.map(&:join) 
5

एलेक्स Kliuchnikau के जवाब के अलावा, मैं जोड़ देंगे कि #join जब धागा Queue#pop के लिए इंतज़ार कर रहा है इस त्रुटि बढ़ा सकता है। एक सरल और सचेत समाधान एक टाइमआउट के साथ #join पर कॉल करता है।

यह रूबी 2.2 से है।2:

[27] pry(main)> q=Queue.new 
=> #<Thread::Queue:0x00000003a39848> 
[30] pry(main)> q << "asdggg" 
=> #<Thread::Queue:0x00000003a39848> 
[31] pry(main)> q << "as" 
=> #<Thread::Queue:0x00000003a39848> 
[32] pry(main)> t = Thread.new { 
[32] pry(main)* while s = q.pop 
[32] pry(main)*  puts s 
[32] pry(main)* end 
[32] pry(main)* } 
asdggg 
as 
=> #<Thread:[email protected](pry):34 sleep> 
[33] pry(main)> q << "asg" 
asg 
=> #<Thread::Queue:0x00000003a39848> 
[34] pry(main)> q << "ashg" 
ashg 
=> #<Thread::Queue:0x00000003a39848> 
[35] pry(main)> t.join 
fatal: No live threads left. Deadlock? 
from (pry):41:in `join' 
[36] pry(main)> t.join(5) 
=> nil 
+0

क्या होगा यदि कतार एक HTTP निरंतर कनेक्शन है? जैसे लाइव स्ट्रीम, और स्ट्रीम में परिणाम यादृच्छिक है, t.join (5) अभी भी काम करता है? –

+0

@crazy_phage, मेरे पास इस उपयोग के मामले में नहीं है लेकिन मुझे नहीं लगता कि यह क्यों काम नहीं करना चाहिए। लगातार HTTP कनेक्शन के मामले में, मुझे लगता है कि आप एक टाइमआउट लागू कर रहे हैं जिसके बाद कनेक्शन बंद होना चाहिए, सही? यदि आप हमेशा के लिए इंतजार करना चाहते हैं, तो आप 10 साल की तरह एक बहुत बड़ा मूल्य निर्धारित कर सकते हैं। – akostadinov

+0

अच्छी तरह से यह है कि http कनेक्शन एक पाइप है और मेरे पास पाइप से पढ़ने के लिए एक और धागा है, अगर मैं t.join j.join 5 का उपयोग नहीं करता, तो यह क्रैश हो जाएगा, लेकिन मुझे नहीं पता कि यह क्यों हो रहा है, coz I भाग गया कि साइडकीक में, लॉग कुछ भी नहीं दिखाया। तो, मैंने अभी आपका जवाब देखा, और मुझे लगता है कि ऐसा इसलिए होता है। –

संबंधित मुद्दे