2009-11-08 12 views
11

चलाने के लिए प्रतीत होता है मैं एक पायथन परियोजना में धागे का उपयोग करने की कोशिश कर रहा हूं, लेकिन थ्रेड्स मेरे कोड में व्यवहार करने के रूप में व्यवहार नहीं कर रहे हैं। ऐसा लगता है कि सभी धागे अनुक्रमिक रूप से चलते हैं (यानी थ्रेड 2 थ्रेड 1 सिरों के बाद शुरू होता है, वे दोनों एक ही समय में शुरू नहीं होते हैं)। मैंने इसका परीक्षण करने के लिए एक सरल लिपि लिखी, और वह अनुक्रमिक रूप से धागे चलाता है।पायथन थ्रेडिंग अनुक्रमिक रूप से

import threading 

def something(): 
    for i in xrange(10): 
     print "Hello" 

def my_thing(): 
    for i in xrange(10): 
     print "world" 

threading.Thread(target=something).start() 
threading.Thread(target=my_thing).start() 

यहाँ उत्पादन मैं इसे चलने से प्राप्त होते हैं:

Hello 
Hello 
Hello 
Hello 
Hello 
Hello 
Hello 
Hello 
Hello 
Hello 
world 
world 
world 
world 
world 
world 
world 
world 
world 
world 

समान व्यवहार छोरों की पुनरावृत्तियों की विशाल संख्या के मध्य मनाया जाता है।

मैंने वेब और पुराने एसओ उत्तरों की खोज करने की कोशिश की, लेकिन मुझे कुछ भी मदद नहीं मिली। क्या कोई यह बता सकता है कि इस कोड के साथ क्या गलत है?

उत्तर

13

वर्तमान में अजगर में, कुछ निर्दिष्ट बाइटकोड निर्देशों को निष्पादित करने के बाद धागे बदल जाते हैं। वे एक ही समय में नहीं चलते हैं। आपके पास केवल समानांतर में थ्रेड निष्पादित होंगे जब उनमें से एक कुछ I/O-गहन या पाइथन-प्रभावित मॉड्यूल नहीं कहता है जो जीआईएल (ग्लोबल दुभाषिया लॉक) जारी कर सकता है।

मुझे यकीन है कि अगर आप 10000 की तरह कुछ लूपों को टक्कर मारते हैं तो आपको आउटपुट मिश्रित हो जाएगा। याद रखें कि केवल दूसरे धागे को झुकाव करने में भी "बहुत" समय लगता है।

+0

10000 पुनरावृत्तियों के साथ वही व्यवहार अपडेट किया है – MAK

+0

वास्तविक प्रोजेक्ट पर जिस पर मैं काम कर रहा हूं, थ्रेड्स में से एक एक अनंत लूप है जो संदेशों के लिए सुनता है और कॉलबैक फ़ंक्शन को कॉल करता है वे पहुंचें। यह सिर्फ सभी अन्य धागे को ब्लॉक करता है। दुर्भाग्य से, वास्तविक पाश कोड को संशोधित नहीं किया जा सकता है (मैं केवल धागे के भीतर कक्षा के रन() विधि को कॉल करता हूं)। – MAK

+0

जब मैं इस तरह की स्क्रिप्ट चलाता हूं: './pythr.py | uniq -c' मुझे मिलता है: 8969 हैलो | 1 हैलो वर्ल्ड | 6626 विश्व | 1 | 3373 दुनिया | 1030 हैलो। तो यह नियंत्रण बदलता है - बस इतना नहीं ... – viraptor

10

उस समय में पहली थ्रेड लूप और प्रिंट पहले से शुरू करने के लिए दूसरा धागा लगता है।

यहां ऐसा लगता है, आप कुछ नरक को उत्सर्जित करने के बाद शुरू होने वाले दूसरे धागे को देख सकते हैं।

Hello 
Hello 
Hello 
Hello 
Hello 
Helloworld 

Helloworld 

Helloworld 

Helloworld 

Helloworld 

world 
world 
world 
world 
world 

बीटीडब्ल्यू: आपका उदाहरण बिल्कुल सार्थक नहीं है। थ्रेड के लिए एकमात्र कारण आईओ है, और आईओ धीमा है। आप आईओ अनुकरण करने के लिए कुछ नींद जोड़ते हैं यह काम करना चाहिए के रूप में उम्मीद:

import threading 
from time import sleep 

def something(): 
    for i in xrange(10): 
     sleep(0.01) 
     print "Hello" 

def my_thing(): 
    for i in xrange(10): 
     sleep(0.01) 
     print "world" 

threading.Thread(target=something).start() 
threading.Thread(target=my_thing).start() 

एक जंगली मिश्रण दिखाई देता है:

worldHello 

Helloworld 

Helloworld 

worldHello 

Helloworld 

Helloworld 

worldHello 

Helloworld 

worldHello 

Helloworld 
+2

मुझे इस तरह के आउटपुट नहीं मिलते हैं, यहां तक ​​कि लूप के पुनरावृत्तियों की बहुत बड़ी/छोटी संख्या के साथ भी। मेरे कंप्यूटर पर यह हमेशा अनुक्रमिक है। मुझे लगता है कि यह ओएस/प्रोसेसर निर्भर है, जैसा कि एबीएक्स ने सुझाव दिया था। – MAK

+0

जैसा कि मैंने अपने प्रश्न में कहा था, यह मेरी समस्या के लिए सिर्फ एक उदाहरण है, न कि जिस कोड के साथ मैं काम कर रहा हूं (जो कि बहुत बड़ा है)। मेरे वास्तविक कोड में, धागे में से एक डीबीस सिग्नल के लिए एक लूप सुनता है। – MAK

3

यह वास्तव में अपने ऑपरेटिंग सिस्टम की अनुसूचक, आपके प्रोसेसर पर निर्भर करता है।
इसके अलावा, यह ज्ञात है कि GIL (पीडीएफ) की वजह से सीपीथॉन के धागे सही नहीं हैं, जो संक्षेप में इसका मतलब है कि कई बार धागे अनुक्रमिक रूप से चलते हैं, या उस तरह के कुछ।

+2

आप शायद मतलब है कि सीपीथन धागे जीआईएल से पीड़ित हैं ... कहते हैं, जिथन में कोई जीआईएल नहीं है। – EOL

+0

@EOL - आप सही हैं, मैंने जवाब – abyx

4

व्यवहार का उपयोग यह भी हो सकता है कि सिस्टम का उपयोग एक प्रोसेसर या एकाधिक प्रोसेसर है, जैसा डेविड बीज़ली द्वारा this talk द्वारा समझाया गया है।

जैसा कि वायरैप्टर कहते हैं, पहला धागा sys.getcheckinterval() बाइटकोड (डिफ़ॉल्ट रूप से 100) निष्पादित करने के बाद जीआईएल जारी करेगा। डेविड बीज़ली का कहना है कि एक प्रोसेसर सिस्टम पर दूसरे धागे को फिर से लेने का मौका मिलेगा। हालांकि एक बहु-कोर सिस्टम पर दूसरा धागा एक अलग कोर पर चल रहा है, और पहला धागा लॉक को पुनः प्राप्त करने का प्रयास करेगा और शायद सफल होगा क्योंकि ओएस में प्रोसेसर स्विच करने का समय नहीं होगा। इसका मतलब यह है कि एक सीपीयू-बाउंड थ्रेड वाले बहु-कोर सिस्टम पर अन्य धागे कभी भी नहीं देख पाएंगे।

इस तरह के रास्ते में दोनों लूपों को नींद का विवरण जोड़ना है ताकि वे अब नहीं रहें सीपीयू बाध्य

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