"थ्रेड-सेफ" शब्द का अर्थ क्या है?


367

क्या इसका मतलब है कि दो धागे अंतर्निहित डेटा को एक साथ नहीं बदल सकते हैं? या क्या इसका मतलब यह है कि दिए गए कोड सेगमेंट प्रेडिक्टेबल रिजल्ट के साथ चलेगा जब कई थ्रेड्स उस कोड सेगमेंट को निष्पादित कर रहे हैं?


8
इस मामले के बारे में यहाँ एक दिलचस्प चर्चा देखी गई: blogs.msdn.com/ericlippert/archive/2009/10/19/…
सेबेस्टियन

जवाबों:


256

विकिपीडिया से:

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

थ्रेड सुरक्षा प्राप्त करने के कुछ तरीके हैं:

पुन: entrancy:

कोड को इस तरह से लिखना कि इसे एक कार्य द्वारा आंशिक रूप से निष्पादित किया जा सकता है, दूसरे कार्य द्वारा पुन: प्रस्तुत किया जा सकता है, और फिर मूल कार्य से फिर से शुरू किया जा सकता है। इसके लिए स्थिर या वैश्विक चर के बजाय, आमतौर पर प्रत्येक कार्य के लिए स्थानीय चर में राज्य की जानकारी को सहेजने की आवश्यकता होती है।

आपसी बहिष्कार:

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

धागा-स्थानीय भंडारण:

चर स्थानीयकृत हैं ताकि प्रत्येक धागे की अपनी निजी प्रति हो। ये चर उप-मार्ग और अन्य कोड सीमाओं में अपने मूल्यों को बनाए रखते हैं, और थ्रेड-सुरक्षित होते हैं, क्योंकि वे प्रत्येक थ्रेड के लिए स्थानीय होते हैं, भले ही जो कोड उन्हें एक्सेस करता है, वे फिर से सुगंधित हो सकते हैं।

परमाणु संचालन:

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

अधिक पढ़ें:

http://en.wikipedia.org/wiki/Thread_safety



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

20
जब Google का पहला परिणाम खोजा गया है, तो इसे यहाँ निरर्थक बनाने का कोई मतलब नहीं है।
रणवीर

आपका क्या मतलब है "एक फ़ंक्शन को एक्सेस करने वाला कोड"? फंक्शन को अंजाम दिया जाना ही कोड है, है ना?
कोरे तुगे

82

थ्रेड-सुरक्षित कोड वह कोड होता है जो कई थ्रेड्स को एक साथ निष्पादित कर रहा है, भले ही वह काम करेगा।

http://mindprod.com/jgloss/threadsafe.html


34
उसी प्रक्रिया के भीतर!
अली अफशार

दरअसल, इसी प्रक्रिया में :)
मारेक ब्लोटनी

4
"कोड लिखने के लिए जो हफ्तों तक चलेगा चरम व्यामोह लेता है।" यह एक उद्धरण है जो मुझे पसंद है :)
जिम टी

5
ओह! यह उत्तर केवल प्रश्न को शांत करता है! --- और केवल एक ही प्रक्रिया के भीतर क्यों ??? यदि कोड विफल हो जाता है जब कई थ्रेड इसे विभिन्न प्रक्रियाओं से निष्पादित करते हैं, तो, यकीनन, ("साझा मेमोरी" डिस्क फ़ाइल में हो सकती है), यह थ्रेड सुरक्षित नहीं है !!
चार्ल्स ब्रेटाना

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

50

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

totalRequests = totalRequests + 1
MOV EAX, [totalRequests]   // load memory for tot Requests into register
INC EAX                    // update register
MOV [totalRequests], EAX   // store updated value back to memory
  1. पहली शर्त यह है कि स्मृति स्थान हैं जो एक से अधिक थ्रेड से सुलभ हैं। आमतौर पर, ये स्थान वैश्विक / स्थिर चर होते हैं या वैश्विक / स्थैतिक चर से पहुंच योग्य स्मृति होती है। प्रत्येक थ्रेड को फंक्शन / मेथड स्कोप्ड लोकल वैरिएबल के लिए अपना स्टैक फ्रेम मिलता है, इसलिए ये लोकल फंक्शन / मेथड वैरिएबल, ओटोह, (जो स्टैक पर होते हैं) केवल उसी स्टैक से एक्सेस होते हैं जो उस स्टैक का मालिक होता है।
  2. दूसरी शर्त यह है कि कार्यक्रम को सही ढंग से कार्य करने के लिए एक संपत्ति है (जिसे अक्सर एक अपरिवर्तनीय कहा जाता है ), जो इन साझा मेमोरी स्थानों से जुड़ा होता है, जो सही या वैध होना चाहिए। उपरोक्त उदाहरण में, संपत्ति यह है कि " कुल रस्में किसी भी धागे की वृद्धि के बयान के किसी भी भाग को निष्पादित करने की कुल संख्या का सटीक रूप से प्रतिनिधित्व करना चाहिए। "। आमतौर पर, इस अपरिवर्तनीय संपत्ति को सही होने के लिए अपडेट होने से पहले (इस मामले में, TotalRequests को एक सटीक गिनती पकड़नी होगी) सही रखने की आवश्यकता है।
  3. तीसरी शर्त यह है कि अपरिवर्तनीय संपत्ति वास्तविक अद्यतन के कुछ हिस्से के दौरान नहीं है। (यह प्रसंस्करण के कुछ भाग के दौरान क्षणिक रूप से अमान्य या गलत है)। इस विशेष मामले में, जब तक अद्यतन मूल्य संग्रहीत नहीं किया जाता है, तब तक कुल धन प्राप्त होता है। संतुष्ट है।
  4. एक दौड़ के लिए होने वाली चौथी और अंतिम शर्त (और कोड के लिए इसलिए "थ्रेड-सेफ" नहीं होना चाहिए) यह है कि एक और थ्रेड साझा मेमोरी तक पहुंचने में सक्षम होना चाहिए, जबकि इंवेरिएंट टूट गया है, जिससे असंगत या गलत व्यवहार।

6
यह केवल डेटा दौड़ के रूप में जाना जाता है , और निश्चित रूप से महत्वपूर्ण है। फिर भी, ऐसे अन्य तरीके हैं कि कैसे कोड थ्रेड सुरक्षित नहीं हो सकता है - उदाहरण के लिए खराब लॉकिंग जिससे गतिरोध हो सकता है। यहां तक ​​कि कुछ आसान जैसे कि System.exit () एक जावा थ्रेड में कहीं न कहीं उस कोड को सुरक्षित बनाता है।
इंगो

2
मुझे लगता है कि कुछ हद तक यह शब्दार्थ है, लेकिन मेरा तर्क है कि खराब लॉकिंग कोड जो गतिरोध का कारण बन सकता है, वह कोड कैफे नहीं बनाता है। सबसे पहले, पहले स्थान पर कोड को लॉक करने की आवश्यकता नहीं है जब तक कि एक दौड़ की स्थिति, जैसा कि ऊपर वर्णित है, संभव नहीं है। फिर, यदि आप लॉकिंग कोड को इस तरह से लिखते हैं जैसे कि गतिरोध पैदा करने के लिए, यह थ्रेड-असुरक्षित नहीं है, तो यह केवल बुरा कोड है।
चार्ल्स ब्रेटाना

1
लेकिन ध्यान दें कि गतिरोध एकल-थ्रेडेड चलने पर नहीं होगा, इसलिए हममें से अधिकांश के लिए यह निश्चित रूप से "थ्रेड-सेफ" (नहीं) के सहज अर्थ के तहत आएगा।
जॉन कूम्ब्स

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

34

मुझे इसकी समझ के लिए ब्रायन गोएत्ज़ के जावा कंजेरिएशन इन प्रैक्टिस की परिभाषा पसंद है

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


यह परिभाषा अधूरी है और विशिष्ट नहीं है, और निश्चित रूप से व्यापक नहीं है। कितनी बार इसे सुरक्षित रूप से चलाना चाहिए, बस एक बार? दस गुना? हर बार? 80% समय? और यह निर्दिष्ट नहीं करता है कि यह "असुरक्षित" क्या बनाता है। यदि यह सुरक्षित रूप से चलाने में विफल रहता है, लेकिन विफलता इसलिए थी क्योंकि शून्य त्रुटि से विभाजित होता है, क्या इससे धागा बनता है- "असुरक्षित"?
चार्ल्स ब्रेटाना

अगली बार और अधिक नागरिक बनें और शायद हम चर्चा कर सकें। यह रेडिट नहीं है और मैं असभ्य लोगों से बात करने के मूड में नहीं हूं।
बुउ गुयेन

आपकी व्याख्या किसी और की परिभाषा के बारे में टिप्पणी करती है जैसा कि खुद को अपमानित करना है। भावनात्मक रूप से प्रतिक्रिया करने से पहले आपको पदार्थ को पढ़ने और समझने की आवश्यकता है। मेरी टिप्पणी के बारे में कोई बात नहीं। मैं परिभाषा के अर्थ के बारे में बात कर रहा था। क्षमा करें यदि मैंने जिन उदाहरणों का उपयोग किया है, उस बिंदु का वर्णन आपको असहज करता है।
चार्ल्स ब्रेटन

28

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

यह ध्यान देने योग्य है कि यह कभी-कभी कंप्यूटर समय और अधिक जटिल कोडिंग की लागत पर आता है, इसलिए यह हमेशा वांछनीय नहीं होता है। यदि किसी वर्ग को केवल एक धागे पर सुरक्षित रूप से उपयोग किया जा सकता है, तो ऐसा करना बेहतर हो सकता है।

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


22

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


21

इसे समझने का एक आसान तरीका है, वह कोड जो थ्रेड-सेफ़ नहीं है। वहाँ दो मुख्य मुद्दा है कि अवांछित व्यवहार करने के लिए एक लड़ी पिरोया आवेदन कर देगा।

  • लॉकिंग के बिना साझा किए गए चर को एक्सेस करना
    इस चर को फ़ंक्शन को निष्पादित करते समय किसी अन्य थ्रेड द्वारा संशोधित किया जा सकता है। आप इसे अपने कार्य के व्यवहार के बारे में सुनिश्चित करने के लिए एक लॉकिंग तंत्र के साथ रोकना चाहते हैं। अंगूठे का सामान्य नियम कम से कम समय के लिए ताला रखना है।

  • साझा चर पर आपसी निर्भरता के कारण गतिरोध
    यदि आपके पास दो साझा चर A और B. एक फ़ंक्शन में हैं, तो आप A को पहले लॉक करते हैं, बाद में आप B. को लॉक करते हैं। किसी अन्य फ़ंक्शन में, आप B को लॉक करना शुरू करते हैं और थोड़ी देर बाद, आप A. को लॉक करते हैं। एक संभावित गतिरोध है जहां पहला फ़ंक्शन बी के अनलॉक होने का इंतजार करेगा जब दूसरा फ़ंक्शन ए के अनलॉक होने का इंतजार करेगा। यह समस्या संभवतः आपके विकास के वातावरण में और केवल समय-समय पर नहीं होगी। इससे बचने के लिए, सभी ताले हमेशा एक ही क्रम में होने चाहिए।


9

हां और ना।

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

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


9

संक्षेप में, बहु थ्रेडेड वातावरण में कई चीजें गलत हो सकती हैं (निर्देश पुन: व्यवस्थित करना, आंशिक रूप से निर्मित वस्तुएं, एक ही चर का सीपीयू स्तर पर कैशिंग के कारण विभिन्न थ्रेड्स में अलग-अलग मान होना)।

मुझे Java Concurrency द्वारा प्रैक्टिस में दी गई परिभाषा पसंद है :

[कोड का एक भाग] थ्रेड-सुरक्षित है यदि यह कई थ्रेड्स से एक्सेस करने पर सही ढंग से व्यवहार करता है, भले ही रनटाइम वातावरण द्वारा उन थ्रेड्स के निष्पादन का शेड्यूलिंग या इंटरलेयिंग, और बिना किसी अतिरिक्त सिंक्रनाइज़ेशन या अन्य समन्वय के भाग पर। कॉलिंग कोड।

द्वारा सही ढंग से वे अपनी विशिष्टताओं के अनुपालन में मतलब है कि कार्यक्रम बर्ताव करती है।

उदाहरण दिया

कल्पना कीजिए कि आप एक काउंटर लागू करते हैं। आप कह सकते हैं कि यह सही ढंग से व्यवहार करता है यदि:

  • counter.next() वह मान कभी नहीं लौटाता है जो पहले ही वापस आ चुका है (हम सादगी के लिए कोई अतिप्रवाह आदि नहीं मानते हैं)
  • वर्तमान मान से सभी मान किसी चरण में वापस कर दिए गए हैं (कोई मान नहीं छोड़ा गया है)

एक थ्रेड सुरक्षित काउंटर उन नियमों के अनुसार व्यवहार करेगा, चाहे कितने सूत्र इसे समवर्ती रूप से एक्सेस करते हों (जो आमतौर पर एक भोले कार्यान्वयन की स्थिति नहीं होगी)।

नोट: प्रोग्रामर पर क्रॉस-पोस्ट



5

निर्धारण के साथ धागा सुरक्षा को भ्रमित न करें। थ्रेड-सुरक्षित कोड गैर-नियतात्मक भी हो सकता है। थ्रेडेड कोड के साथ डिबगिंग समस्याओं की कठिनाई को देखते हुए, यह शायद सामान्य मामला है। :-)

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


5

मैं अन्य अच्छे उत्तरों के शीर्ष पर कुछ और जानकारी जोड़ना चाहूंगा।

थ्रेड सुरक्षा से तात्पर्य है कि कई थ्रेड्स मेमोरी असंगति त्रुटियों के बिना एक ही ऑब्जेक्ट में डेटा लिख ​​/ पढ़ सकते हैं। अत्यधिक बहु थ्रेडेड प्रोग्राम में, थ्रेड सेफ प्रोग्राम साझा डेटा पर दुष्प्रभाव नहीं डालता है

अधिक जानकारी के लिए इस एसई प्रश्न पर एक नजर:

थ्रेडसेफ़ का क्या अर्थ है?

थ्रेड सेफ प्रोग्राम मेमोरी की संगति की गारंटी देता है

उन्नत समवर्ती एपीआई पर ओरेकल प्रलेखन पृष्ठ से :

मेमोरी संगति गुण:

जावा ™ लैंग्वेज स्पेसिफिकेशन का चैप्टर 17, मेमोरी ऑपरेशंस पर होने वाले रिलेशन को परिभाषित करता है, जैसे कि शेयर्ड वेरिएबल्स को रीड और राइट करता है। एक थ्रेड द्वारा लिखने के परिणाम को दूसरे थ्रेड द्वारा केवल पढ़ने के लिए दृश्यमान होने की गारंटी दी जाती है, यदि लेखन ऑपरेशन होता है-रीड ऑपरेशन से पहले

synchronizedऔर volatileनिर्माणों, साथ ही Thread.start()और Thread.join()तरीकों, कर सकते हैं प्रपत्र होता है-पहले रिश्ते।

सभी वर्गों java.util.concurrentऔर इसके उप- वर्गों की विधियाँ इन गारंटियों को उच्च-स्तरीय सिंक्रनाइज़ेशन तक विस्तारित करती हैं विशेष रूप से:

  1. किसी भी समवर्ती संग्रह में किसी वस्तु को रखने से पहले एक धागे में क्रियाएँ होती हैं-दूसरे धागे में संग्रह से उस तत्व के उपयोग या हटाने के बाद की क्रियाएं।
  2. एक प्रस्तुत करने से पहले एक धागे में कार्रवाई Runnableकरने के लिए एक Executorहोने से पहले इसके निष्पादन शुरू होता है। इसी तरह से Callables के लिए सबमिट किया गया a ExecutorService
  3. Futureपरिणाम के पुनर्प्राप्ति के बाद होने वाली क्रियाओं से पहले होने वाली अतुल्यकालिक संगणना द्वारा लिया गया कार्यFuture.get()किसी अन्य थ्रेड के ।
  4. इस तरह के रूप में एक सफल "प्राप्त" विधि के बाद होने वाली कार्रवाई से पहले तुल्यकालक तरीकों "जारी" करने Lock.unlock, Semaphore.release, and CountDownLatch.countDownसे पहले की कार्रवाईLock.lock, Semaphore.acquire, Condition.await, and CountDownLatch.await एक अन्य थ्रेड में समान सिंक्रनाइज़र ऑब्जेक्ट पर।
  5. धागे की प्रत्येक जोड़ी के लिए जो सफलतापूर्वक ए के माध्यम से वस्तुओं का आदान-प्रदान करते हैं Exchanger, से पहले की कार्रवाईexchange() , प्रत्येक धागे में दूसरे धागे में संबंधित एक्सचेंज () के बाद होने वाले से पहले होती हैं।
  6. कॉल करने से पहले की कार्रवाइयाँ CyclicBarrier.awaitऔर Phaser.awaitAdvance(साथ ही साथ इसके वेरिएंट) भी होती हैं-बैरियर एक्शन द्वारा की जाने वाली एक्शन से पहले की जाने वाली क्रियाएँ, और एक्शन के द्वारा की जाने वाली एक्शन होती हैं-एक्शन से पहले होने वाली एक्शन के बाद अन्य थ्रेड्स में सफल होने के बाद।

4

अन्य उत्तरों को पूरा करने के लिए:

सिंक्रनाइज़ेशन केवल एक चिंता का विषय है जब आपकी विधि में कोड दो चीजों में से एक करता है:

  1. कुछ बाहरी संसाधनों के साथ काम करता है जो सुरक्षित नहीं है।
  2. लगातार ऑब्जेक्ट या क्लास फ़ील्ड को पढ़ता है या बदलता है

इसका मतलब यह है कि आपकी विधि से परिभाषित चर हमेशा थ्रेडसेफ़ हैं। एक विधि के लिए प्रत्येक कॉल में इन चरों का अपना संस्करण होता है। यदि विधि को किसी अन्य थ्रेड द्वारा, या उसी थ्रेड द्वारा कॉल किया जाता है, या यहां तक ​​कि यदि विधि स्वयं को कॉल करती है (पुनरावर्तन), तो इन चरों के मान साझा नहीं किए जाते हैं।

थ्रेड शेड्यूलिंग को राउंड-रॉबिन होने की गारंटी नहीं है । एक कार्य पूरी तरह से एक ही प्राथमिकता के धागे की कीमत पर सीपीयू को हॉग कर सकता है। आप एक विवेक रखने के लिए Thread.yield () का उपयोग कर सकते हैं। थ्रेड की प्राथमिकता को कम करने के लिए आप (जावा में) थ्रेड.सेटपायरिटी (थ्रेड .NORM_PRIORITY-1) का उपयोग कर सकते हैं

इसके अलावा सावधान:

  • इन "थ्रेड-सुरक्षित" संरचनाओं पर पुनरावृति करने वाले अनुप्रयोगों पर बड़ी रनटाइम लागत (पहले से दूसरों द्वारा उल्लिखित)।
  • थ्रेड.स्लीप (5000) 5 सेकंड के लिए सोने के लिए माना जाता है। हालांकि, यदि कोई व्यक्ति सिस्टम समय बदलता है, तो आप बहुत लंबे समय तक सो सकते हैं या बिल्कुल भी समय नहीं ले सकते हैं। OS समय को पूर्ण रूप में दर्ज करता है, सापेक्ष नहीं।

2

हाँ और हाँ। तात्पर्य यह है कि डेटा एक साथ एक से अधिक थ्रेड द्वारा संशोधित नहीं किया गया है। हालाँकि, आपका कार्यक्रम अपेक्षित रूप से काम कर सकता है, और थ्रेड-सेफ दिखाई दे सकता है, भले ही यह मौलिक रूप से न हो।

ध्यान दें कि परिणामों की अप्रत्याशितता 'रेस-कंडीशन्स' का परिणाम है, जिसके परिणामस्वरूप संभवतः डेटा को एक ऑर्डर के अलावा अन्य ऑर्डर में संशोधित किया जा सकता है।


2

आइए इसका उत्तर उदाहरण के तौर पर दें:

class NonThreadSafe {

    private int counter = 0;

    public boolean countTo10() {
        count = count + 1;
        return (count == 10);
    }

countTo10विधि काउंटर करने के लिए एक कहते हैं और फिर TRUE देता गिनती 10 तक पहुँच गया है यह केवल सच एक बार वापस आ जाएगी।

यह तब तक काम करेगा जब तक केवल एक धागा ही कोड चल रहा हो। यदि दो धागे एक ही समय में कोड चलाते हैं तो विभिन्न समस्याएं हो सकती हैं।

उदाहरण के लिए, यदि गिनती 9 के रूप में शुरू होती है, तो एक धागा 1 गणना करने के लिए (10 बना सकता है) जोड़ सकता है, लेकिन फिर एक दूसरा धागा विधि में प्रवेश कर सकता है और पहले धागे से 10 को तुलना करने का मौका देने से पहले 1 फिर से (11 बनाने) जोड़ सकता है। फिर दोनों धागे तुलना करते हैं और पाते हैं कि गिनती 11 है और न ही सही है।

तो यह कोड थ्रेड सुरक्षित नहीं है।

संक्षेप में, सभी बहु-सूत्रण समस्याएं इस तरह की समस्या के कुछ भिन्नता के कारण होती हैं।

इसका समाधान यह सुनिश्चित करना है कि जोड़ और तुलना को अलग नहीं किया जा सकता है (उदाहरण के लिए किसी तरह के सिंक्रनाइज़ेशन कोड द्वारा दो कथनों को घेरकर) या ऐसे समाधान को तैयार करने के लिए जिसमें दो कार्यों की आवश्यकता नहीं होती है। ऐसा कोड थ्रेड-सुरक्षित होगा।


1

कम से कम C ++ में, मुझे लगता है थ्रेड-सेफ को एक मिथ्या नाम के रूप में कि यह नाम से बहुत कुछ छोड़ देता है। थ्रेड-सुरक्षित होने के लिए, कोड को आमतौर पर इसके बारे में सक्रिय होना पड़ता है। यह आमतौर पर एक निष्क्रिय गुणवत्ता नहीं है।

एक वर्ग को चलने के लिए सुरक्षित होने के लिए, इसमें "अतिरिक्त" विशेषताएं होनी चाहिए जो ओवरहेड को जोड़ती हैं। ये विशेषताएं वर्ग के कार्यान्वयन का हिस्सा हैं और आम तौर पर बोलना, इंटरफ़ेस से छिपा हुआ है। यही है, अलग-अलग धागे किसी भी वर्ग के सदस्यों तक पहुंच सकते हैं, कभी भी एक अलग धागे द्वारा समवर्ती पहुंच के साथ संघर्ष करने के बारे में चिंता करने के लिए और ऐसा बहुत आलसी तरीके से कर सकते हैं, सादे पुरानी नियमित मानव कोडिंग शैली का उपयोग किए बिना। सभी कि पागल तुल्यकालन सामान जो पहले से ही कोड के हिम्मत में लुढ़का हुआ है।

और यही कारण है कि कुछ लोग इस शब्द का उपयोग करना पसंद करते हैं आंतरिक रूप से सिंक्रनाइज़

शब्दावली सेट

इन विचारों के लिए शब्दावली के तीन मुख्य सेट हैं जिनका मैंने सामना किया है। पहला और ऐतिहासिक रूप से अधिक लोकप्रिय (लेकिन बदतर) है:

  1. सुरक्षित धागा
  2. धागा सुरक्षित नहीं है

दूसरा (और बेहतर) है:

  1. धागा प्रमाण
  2. धागा संगत
  3. धागा शत्रुतापूर्ण

एक तीसरा है:

  1. आंतरिक रूप से सिंक्रनाइज़
  2. बाहरी रूप से सिंक्रनाइज़
  3. unsynchronizeable

उपमा

धागा सुरक्षित ~ धागा सबूत ~ आंतरिक रूप से सिंक्रनाइज़

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

थ्रेड-सेफ (लेकिन अच्छा नहीं) ~ थ्रेड संगत ~ बाह्य रूप से सिंक्रनाइज़ ~ फ्री-थ्रेडेड

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

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

थ्रेड सुरक्षित नहीं है (और खराब) ~ थ्रेड शत्रुता ~ अनसंकटनीय

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

क्यों धागा सुरक्षित एट अल। एक बुरा शब्दावली सेट हैं

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

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

हमारे लक्ष्यों की याद दिलाएं

अनिवार्य रूप से, हमारा लक्ष्य अराजकता को कम करना है।

हम ऐसा करते हैं कि निर्धारक प्रणाली बनाकर हम भरोसा कर सकते हैं। नियतत्ववाद महंगा है, ज्यादातर अवसरवाद की समानता, पाइपलाइनिंग, और रीऑर्डरिंग को खोने के कारण है। हम नियतत्ववाद की मात्रा को कम करने की कोशिश करते हैं, हमें अपनी लागत कम रखने की आवश्यकता है, साथ ही ऐसे निर्णय लेने से भी बचना चाहिए जो आगे चलकर यह तय कर सकते हैं कि हम किस छोटे निर्धारकवाद को बर्दाश्त कर सकते हैं।

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


1

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

उदाहरण के लिए, सरणी-सूचियों और हैश सेट जैसे कई संग्रह इस बात की गारंटी देंगे कि यदि उन्हें शुरू में एक धागे से विशेष रूप से एक्सेस किया जाता है, और किसी संदर्भ में किसी अन्य धागे के दिखाई देने के बाद उन्हें संशोधित नहीं किया जाता है, तो उन्हें किसी भी संयोजन द्वारा मनमाने ढंग से पढ़ा जा सकता है। हस्तक्षेप के बिना धागे के।

अधिक दिलचस्प बात यह है कि कुछ हैश-सेट संग्रह जैसे कि मूल गैर-जेनेरिक .NET में .NET, गारंटी दे सकता है कि जब तक कोई आइटम कभी भी हटाया नहीं जाता है, और बशर्ते कि केवल एक धागा उन्हें कभी भी लिखता है, कोई भी धागा जो कोशिश करता है संग्रह पढ़ना व्यवहार करेगा जैसे कि एक संग्रह तक पहुंच जहां अद्यतन में देरी हो सकती है और मनमाना क्रम में हो सकता है, लेकिन जो अन्यथा सामान्य रूप से व्यवहार करेगा। यदि थ्रेड # 1 एक्स और फिर वाई जोड़ता है, और थ्रेड # 2 के लिए देखता है और वाई और फिर एक्स को देखता है, तो थ्रेड # 2 के लिए यह देखना संभव होगा कि वाई मौजूद है लेकिन एक्स नहीं करता है; इस तरह का व्यवहार "थ्रेड-सेफ" है या नहीं, इस बात पर निर्भर करेगा कि थ्रेड # 2 उस संभावना से निपटने के लिए तैयार है या नहीं।

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


0

सरल शब्दों में: P यदि कोड के एक ब्लॉक पर कई थ्रेड्स निष्पादित करना सुरक्षित है तो यह थ्रेड सेफ है *

*शर्तें लागू

अन्य उत्तर के द्वारा शर्तों का उल्लेख किया जाता है जैसे 1. परिणाम एक ही होना चाहिए यदि आप एक धागा या इसके ऊपर कई धागे निष्पादित करते हैं आदि।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.