2011-06-11 15 views
96

मुझे लगता है कि अक्सर सूचियों और .pop() के बजाय कई धागे के साथ कतारों का उपयोग करने का सुझाव दिया जाता है। क्या ऐसा इसलिए है क्योंकि सूचियां थ्रेड-सुरक्षित नहीं हैं, या किसी अन्य कारण से?सूचियां धागे-सुरक्षित हैं?

उत्तर

124

सूचियां स्वयं थ्रेड-सुरक्षित हैं। सीपीथॉन में जीआईएल उनके समवर्ती उपयोग के खिलाफ सुरक्षा करता है, और अन्य कार्यान्वयन उनकी सूची कार्यान्वयन के लिए एक अच्छी तरह से दाग या एक सिंक्रनाइज़ डेटाटाइप का उपयोग करने का ख्याल रखता है। हालांकि, सूचियों स्वयं समवर्ती रूप से पहुंचने के प्रयासों से दूषित नहीं हो सकते हैं, सूचियों के डेटा संरक्षित नहीं है। उदाहरण के लिए:

L[0] += 1 

वास्तव में, एक अगर एक और धागा एक ही बात करता है के द्वारा [0] एल बढ़ाने के लिए क्योंकि += एक परमाणु आपरेशन नहीं है इसकी गारंटी नहीं है। (पाइथन में बहुत कम ऑपरेशन वास्तव में परमाणु हैं, क्योंकि उनमें से अधिकतर मनमानी पायथन कोड कहला सकते हैं।) आपको कतार का उपयोग करना चाहिए क्योंकि यदि आप केवल एक असुरक्षित सूची का उपयोग करते हैं, तो आप गलत आइटम प्राप्त या हटा सकते हैं क्योंकि दौड़ की स्थिति का।

+0

डेक भी थ्रेड-सुरक्षित है? यह मेरे उपयोग के लिए अधिक उपयुक्त लगता है। – lemiant

+15

सभी पायथन वस्तुओं में समान प्रकार की धागा-सुरक्षितता होती है - वे स्वयं भ्रष्ट नहीं होते हैं, लेकिन उनका डेटा हो सकता है। collections.deque Queue.Queue ऑब्जेक्ट्स के पीछे क्या है। यदि आप दो धागे से चीजों तक पहुंच रहे हैं, तो आपको वास्तव में Queue.Queue ऑब्जेक्ट्स का उपयोग करना चाहिए। वास्तव में। –

+0

सुस्त, डेक थ्रेड-सुरक्षित है। फ्लुएंट पायथन के अध्याय 2 से: "वर्ग संग्रह .deque एक थ्रेड-सुरक्षित डबल-एंडेड कतार है जो तेजी से डालने और दोनों सिरों से हटाने के लिए डिज़ाइन किया गया है। [...] संलग्न और पिपल ऑपरेशन परमाणु हैं, इसलिए डेक सुरक्षित है ताले का उपयोग करने की आवश्यकता के बिना बहु-थ्रेडेड अनुप्रयोगों में LIFO-queue के रूप में उपयोग करें। " –

53

थॉमस के उत्कृष्ट उत्तर में एक बिंदु को स्पष्ट करने के लिए, यह उल्लेख किया जाना चाहिए कि append() धागा सुरक्षित है।

यह कोई चिंता यह है कि डेटा जा रहा है पढ़ एक ही जगह में होगा एक बार हम यह करने के लिए लिखने करने के लिए जाना है, क्योंकि है। append() ऑपरेशन डेटा नहीं पढ़ता है, यह केवल सूची में डेटा लिखता है।

+1

PyList_Append स्मृति से पढ़ रहा है। क्या आपका मतलब है कि एक ही जीआईएल लॉक में पढ़ता है और लिखता है? https://github.com/python/cpython/blob/1cecdbbf1adef9af2ac829c7dbba91352accb1fd/Objects/listobject.c#L303 – amwinter

+1

@amwinter हां, 'PList_Append' पर पूरी कॉल एक जीआईएल लॉक में की जाती है। इसे जोड़ने के लिए किसी ऑब्जेक्ट का संदर्भ दिया जाता है। मूल्यांकन के बाद उस ऑब्जेक्ट की सामग्री को बदला जा सकता है और 'PyList_Append' पर कॉल करने से पहले किया जा सकता है। लेकिन यह अभी भी वही वस्तु होगी, और सुरक्षित रूप से संलग्न होगा (यदि आप 'lst.append (x) करते हैं; ठीक = lst [-1] x' है, तो' ठीक है 'निश्चित रूप से गलत हो सकता है)। आपके द्वारा संदर्भित कोड को शामिल करने के अलावा, संलग्न वस्तु से नहीं पढ़ा जाता है। यह उस सूची को पढ़ता है, और पुन: आवंटित कर सकता है। – greggo

+1

डॉटनकोहेन का मुद्दा यह है कि 'एल [0] + = x'' एल' पर '__getitem__' और फिर' एल' पर '__setitem__' करेगा - यदि' एल' '__iadd__' का समर्थन करता है तो यह चीजें करेगा ऑब्जेक्ट इंटरफ़ेस पर थोड़ा अलग, लेकिन पाइथन दुभाषिया स्तर पर 'एल' पर दो अलग-अलग ऑपरेशन हैं (आप उन्हें संकलित बाइटकोड में देखेंगे)। 'Append' बाइटकोड में एक विधि विधि में किया जाता है। – greggo

28

Here's a comprehensive yet non-exhaustive list of exampleslist संचालन और चाहे वे धागे सुरक्षित हैं या नहीं। obj in a_list भाषा निर्माण here के बारे में उत्तर प्राप्त करने की उम्मीद है।

+0

पहला लिंक मृत प्रतीत होता है। – displayname

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