2012-10-25 10 views
5

मैं निम्नलिखित कोड (from a Ruby tutorial) है। मेरे कंप्यूटर पर, परिणाम ट्यूटोरियल से काफी अलग हैं। join कॉल करने के बाद, मायने रखता है कभी कभी बराबर हैं:लूप्स

count1 : 5321211 
count2 : 6812638 
difference : 0 
count1 : 27307724 
count2 : 27307724 
difference : 0 

और कभी कभी नहीं:

count1 : 4456390 
count2 : 5981589 
difference : 0 
count1 : 25887977 
count2 : 28204117 
difference : 0 

मुझे समझ नहीं आता कि यह कैसे संभव है कि अंतर अभी भी 0 है भले ही मायने रखता है बहुत अलग दिखाने संख्या।

add आपरेशन शायद इस तरह दिखता है:

val = fetch_current(count1) 
add 1 to val 
store val back into count1 

और count2 के लिए कुछ इसी तरह। रूबी धागे के बीच निष्पादन स्विच कर सकता है, इसलिए हो सकता है कि यह एक चर को लिखना समाप्त न हो, लेकिन जब सीपीयू थ्रेड पर वापस आ जाए, तो उसे उस रेखा से जारी रखना चाहिए जहां इसे बाधित किया गया था, है ना?

और अभी भी एक धागा है जो चर में लिख रहा है। यह कैसे संभव है कि loop do ब्लॉक के अंदर, count2 += 1 अधिक बार निष्पादित किया गया है?

+0

'जुड़ने (2)' क्या करना चाहिए? – uday

+0

यह थ्रेड को समाप्त करने के लिए एक सीमा (सेकेंड में) देता है। अगर मैं इसे कॉल नहीं करूंगा, तो कार्यक्रम के अंत तक पहुंचने पर रूबी स्वचालित रूप से थ्रेड काट देगा (इसलिए अनंत 'लूप डू हमेशा समाप्त होगा)। अधिक जानकारी के लिए http://www.ruby-doc.org/core-1.9.3/Thread.html#method-i-join देखें – Tombart

+1

यह दिलचस्प है। रूबी 1.8 पर 'अंतर' हमेशा <> 0 होता है, और गणना 1 से अधिक से भिन्न नहीं होती है, लेकिन रूबी 1.9 पर 'अंतर' हमेशा == 0 होती है लेकिन count1 और count2 एक-दूसरे से अलग होती हैं। – Casper

उत्तर

3

puts "count1 : #{count1}" 

के निष्पादन के लिए कुछ समय (हालांकि यह कम हो सकता है) लेता है। यह एक उदाहरण में नहीं किया जाता है।

puts "count1 : #{count1}" 
puts "count2 : #{count2}" 

अलग मायने रखता है दिखा रहे हैं: इसलिए, यह है कि लगातार दो लाइनों रहस्यमय नहीं है। बस, counter थ्रेड कुछ लूप चक्र चला गया और पहले puts निष्पादित किया गया था, जबकि गणना बढ़ी।

इसी तरह,

difference += (count1 - count2).abs 

गणना की जाती है जब, मायने रखता है सिद्धांत वेतन वृद्धि में जबकि count1count2 से पहले संदर्भित है हो सकता है संदर्भित है। लेकिन उस समय अवधि में निष्पादित कोई आदेश नहीं है, और मुझे लगता है कि count1 को संदर्भित करने में लगने वाला समय counter थ्रेड के लिए एक और लूप के माध्यम से जाने के समय से बहुत छोटा है। ध्यान दें कि पूर्व में किए गए ऑपरेशन बाद में किए गए कार्यों का उचित सबसेट है। यदि अंतर काफी महत्वपूर्ण है, जिसका अर्थ है कि counter- विधि के लिए तर्क कॉल के दौरान थ्रेड चक्र के माध्यम से थ्रेड नहीं चला था, तो count1 और count2 समान मान के रूप में दिखाई देगा।

एक भविष्यवाणी हो जाएगा कि, अगर आप count1 संदर्भित के बाद लेकिन count2 संदर्भित करने से पहले कुछ महंगा गणना शब्दों में कहें, तो difference दिखाई देगा:

difference += (count1.tap{some_expensive_calculation} - count2).abs 
# => larger `difference` 
+0

वास्तव में काउंटरों के बीच काउंटर थ्रेड में 'नींद 0.001' जैसे कुछ डालने से अंतर भी दिखाई देता है। चूंकि काउंटर थ्रेड "व्यस्त लूपिंग" है, मुझे आश्चर्य है कि जासूस थ्रेड को भी 1.9 में चलाने का अधिक मौका मिलता है। नींद के वक्तव्य को अस्थायी रूप से जासूसी थ्रेड चलाने के लिए CPU समय मुक्त करता है, और अंतर दिखाई देता है। – Casper

+1

धन्यवाद, यह समझ में आता है। 'प्रिंट' को 'प्रिंट' द्वारा प्रतिस्थापित करें count1: # {count1}, count2: # {count2} \ n "' काउंटर के बीच अंतर कम कर सकता है। क्योंकि 'puts' को दो कमांड के रूप में निष्पादित किया जाता है और इसलिए थोड़ा और समय लगता है। – Tombart

0

यहाँ जवाब है। मुझे लगता है कि आपने धारणा की है कि join(2) रिटर्न के बाद धागे निष्पादन रोकते हैं।

यह मामला नहीं है! धागे चलते रहते हैं भले ही join(2) निष्पादन (अस्थायी रूप से) मुख्य धागे पर वापस लौटाता है।

आप इस के लिए अपने कोड बदलते हैं तो आपको क्या होता देखेंगे:

... 
counter.join(2) 
spy.join(2) 

counter.kill 
spy.kill 

puts "count1 : #{count1}" 
puts "count2 : #{count2}" 
puts "difference : #{difference}" 

यह गहरे लाल रंग का 1.8, में अलग ढंग से एक सा काम करने के लिए जहां धागे जबकि मुख्य चलाने के लिए एक मौका मिलता है प्रतीत नहीं लगता है धागा निष्पादित कर रहा है।

ट्यूटोरियल शायद रूबी 1.8 के लिए लिखा गया है, लेकिन थ्रेडिंग मॉडल तब से 1.9 में बदल दिया गया है।

वास्तव में यह शुद्ध "भाग्य" था कि यह 1.8 में काम करता था, क्योंकि धागे निष्पादन को समाप्त नहीं करते हैं जब join(2) न तो 1.8 और न ही 1.9 में आता है।

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