2010-04-29 11 views
5

किसी अन्य प्रश्न में कुछ चर्चा ने मुझे उन मामलों को बेहतर ढंग से समझने के लिए प्रोत्साहित किया है जहां बहुप्रचारित पायथन कार्यक्रमों में लॉकिंग की आवश्यकता है।क्या ऐसे कुछ मामले हैं जहां पाइथन धागे सुरक्षित रूप से साझा राज्य में हेरफेर कर सकते हैं?

प्रति this पायथन में थ्रेडिंग पर आलेख, मेरे पास कई ठोस, परीक्षण योग्य उदाहरण हैं जो कई धागे साझा स्थिति तक पहुंच सकते हैं। इस पृष्ठ पर प्रदान की गई उदाहरण दौड़ की स्थिति में एक शब्दकोश में संग्रहीत साझा चर को पढ़ने और छेड़छाड़ करने वाले धागे के बीच दौड़ शामिल है। मुझे लगता है कि यहां एक दौड़ के मामले बहुत स्पष्ट हैं, और सौभाग्य से बेहद टेस्टेबल है।

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

from threading import Thread, Lock 
import operator 

def contains_all_ints(l, n): 
    l.sort() 
    for i in xrange(0, n): 
     if l[i] != i: 
      return False 
    return True 

def test(ntests): 
    results = [] 
    threads = [] 
    def lockless_append(i): 
     results.append(i) 
    for i in xrange(0, ntests): 
     threads.append(Thread(target=lockless_append, args=(i,))) 
     threads[i].start() 
    for i in xrange(0, ntests): 
     threads[i].join() 
    if len(results) != ntests or not contains_all_ints(results, ntests): 
     return False 
    else: 
     return True 

for i in range(0,100): 
    if test(100000): 
     print "OK", i 
    else: 
     print "appending to a list without locks *is* unsafe" 
     exit() 

मैं विफलता (100x 100k बहु संलग्न कर देता है) के बिना ऊपर परीक्षण समाप्त हो गया है: इस परीक्षा विस्तृत रूप से इस तरह के एक दौड़ का प्रदर्शन करने के प्रयास करता है। क्या कोई इसे असफल कर सकता है? क्या ऑब्जेक्ट का एक और वर्ग है जिसे धागे द्वारा परमाणु, वृद्धिशील, संशोधन के माध्यम से गलत व्यवहार करने के लिए बनाया जा सकता है?

क्या इन अंतर्निहित 'परमाणु' अर्थशास्त्र पाइथन में अन्य परिचालनों पर लागू होते हैं? क्या यह सीधे जीआईएल से संबंधित है?

+0

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

उत्तर

7

सूची में शामिल करना थ्रेड-सुरक्षित है, हां। आप केवल जीआईएल धारण करते समय एक सूची में शामिल हो सकते हैं, और सूची append ऑपरेशन (जो कि, काफी सरल ऑपरेशन है) के दौरान जीआईएल को जारी नहीं करने का ख्याल रखती है। ऑर्डर जिसमें विभिन्न थ्रेड के परिचालन परिचालन जाते हैं के माध्यम से निश्चित रूप से पकड़ने के लिए है, लेकिन वे सभी कड़ाई से संचालन संचालन करेंगे क्योंकि जीआईएल को एक परिशिष्ट के दौरान कभी जारी नहीं किया जाता है।

अन्य परिचालनों के लिए यह भी जरूरी नहीं है। पायथन में बहुत सारे ऑपरेशन मनमाने ढंग से पाइथन कोड को निष्पादित कर सकते हैं, जिससे बदले में जीआईएल जारी किया जा सकता है। उदाहरण के लिए, i += 1 तीन अलग-अलग ऑपरेशन हैं, "i", "इसमें 1 जोड़ें" और "इसे i में स्टोर करें"। "इसमें 1 जोड़ें" अनुवाद (इस मामले में) it.__iadd__(1) में अनुवाद करेगा, जो बंद हो सकता है और कर सकता है जो भी इसे पसंद है।

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

1

CPython में, धागा स्विच ings किया जाता है जब sys.getcheckinteval() bycodes निष्पादित किया गया है। तो एक संदर्भ स्विच एक बाइटकोड के निष्पादन के दौरान कभी नहीं हो सकता है, और एक बाइटकोड के रूप में एन्कोड किए गए ऑपरेशंस स्वाभाविक रूप से परमाणु और थ्रेडसेफ होते हैं, जब तक कि बाइटकोड अन्य पायथन कोड निष्पादित नहीं करता है या जी कोड जारी करने वाले सी कोड को कॉल करता है। अंतर्निहित संग्रह प्रकारों (निर्देश, सूची इत्यादि) पर अधिकांश संचालन 'स्वाभाविक रूप से थ्रेडसेफ' श्रेणी में आते हैं।

हालांकि यह एक कार्यान्वयन विवरण है जो पायथन के सी कार्यान्वयन के लिए विशिष्ट है, और इस पर भरोसा नहीं किया जाना चाहिए। पायथन (ज्योथन, आयरनपीथन, पायपी आदि) के अन्य संस्करण एक ही तरीके से व्यवहार नहीं कर सकते हैं। इस बात की कोई गारंटी नहीं है कि सीपीथॉन के भविष्य के संस्करण इस व्यवहार को बनाए रखेंगे।

+0

यह क्या हो रहा था इसके बारे में मेरी अंतर्ज्ञान के बाद, लेकिन मैंने कभी भी अन्य कार्यान्वयन की जांच करने के लिए सोचा नहीं होगा। मैं केवल सीपीथन का उपयोग कर रहा हूं। मैंने विचार किया कि, वैकल्पिक कार्यान्वयन के खिलाफ कोड भविष्य के सबूत बनाने के लिए, इस विवरण पर भरोसा नहीं किया जाना चाहिए। –

+0

बाइटकोड भेद अधिकतर दिलचस्प नहीं है, क्योंकि लगभग सभी बाइटकोड में अधिक पायथन कोड निष्पादित करने की क्षमता होती है, और कुछ जिनके पास जीआईएल को खुद को जारी करने की क्षमता नहीं होती है। 'list.append()', उदाहरण के लिए, एक बाइटकोड नहीं है, और वास्तविक 'append' कार्य' CALL_FUNCTION' ऑपोड द्वारा निष्पादित किया जाता है, जो * अधिक संभावना * निष्पादित करने के लिए * अत्यधिक संभावना है :-) –