क्या इसका मतलब है कि दो धागे अंतर्निहित डेटा को एक साथ नहीं बदल सकते हैं? या क्या इसका मतलब यह है कि दिए गए कोड सेगमेंट प्रेडिक्टेबल रिजल्ट के साथ चलेगा जब कई थ्रेड्स उस कोड सेगमेंट को निष्पादित कर रहे हैं?
क्या इसका मतलब है कि दो धागे अंतर्निहित डेटा को एक साथ नहीं बदल सकते हैं? या क्या इसका मतलब यह है कि दिए गए कोड सेगमेंट प्रेडिक्टेबल रिजल्ट के साथ चलेगा जब कई थ्रेड्स उस कोड सेगमेंट को निष्पादित कर रहे हैं?
जवाबों:
विकिपीडिया से:
थ्रेड सुरक्षा एक कंप्यूटर प्रोग्रामिंग अवधारणा है जो बहु-थ्रेडेड प्रोग्राम के संदर्भ में लागू होती है। कोड का एक टुकड़ा थ्रेड-सुरक्षित है यदि यह एक साथ कई थ्रेड्स के निष्पादन के दौरान सही ढंग से कार्य करता है। विशेष रूप से, इसे एक ही साझा किए गए डेटा तक पहुँचने के लिए कई थ्रेड्स की आवश्यकता को पूरा करना होगा, और किसी भी समय केवल एक थ्रेड द्वारा डेटा के साझा किए जाने की आवश्यकता होगी।
थ्रेड सुरक्षा प्राप्त करने के कुछ तरीके हैं:
पुन: entrancy:
कोड को इस तरह से लिखना कि इसे एक कार्य द्वारा आंशिक रूप से निष्पादित किया जा सकता है, दूसरे कार्य द्वारा पुन: प्रस्तुत किया जा सकता है, और फिर मूल कार्य से फिर से शुरू किया जा सकता है। इसके लिए स्थिर या वैश्विक चर के बजाय, आमतौर पर प्रत्येक कार्य के लिए स्थानीय चर में राज्य की जानकारी को सहेजने की आवश्यकता होती है।
आपसी बहिष्कार:
साझा किए गए डेटा तक पहुंच को तंत्र का उपयोग करके क्रमबद्ध किया जाता है जो किसी भी समय केवल साझा किए गए डेटा को पढ़ता या लिखता है। यदि कोड का एक टुकड़ा डेटा के कई साझा टुकड़ों तक पहुंचता है, तो बड़ी देखभाल की आवश्यकता होती है - समस्याओं में दौड़ की स्थिति, गतिरोध, लाइवलॉक, भुखमरी, और कई अन्य ऑपरेटिंग सिस्टम पाठ्यपुस्तकों में शामिल विभिन्न विभिन्न बीमारियों शामिल हैं।
धागा-स्थानीय भंडारण:
चर स्थानीयकृत हैं ताकि प्रत्येक धागे की अपनी निजी प्रति हो। ये चर उप-मार्ग और अन्य कोड सीमाओं में अपने मूल्यों को बनाए रखते हैं, और थ्रेड-सुरक्षित होते हैं, क्योंकि वे प्रत्येक थ्रेड के लिए स्थानीय होते हैं, भले ही जो कोड उन्हें एक्सेस करता है, वे फिर से सुगंधित हो सकते हैं।
परमाणु संचालन:
साझा किए गए डेटा को परमाणु संचालन का उपयोग करके एक्सेस किया जाता है जिसे अन्य थ्रेड्स द्वारा बाधित नहीं किया जा सकता है। इसके लिए आमतौर पर विशेष मशीन भाषा निर्देशों का उपयोग करना पड़ता है, जो एक रनटाइम लाइब्रेरी में उपलब्ध हो सकता है। चूंकि ऑपरेशन परमाणु हैं, साझा किए गए डेटा को हमेशा एक वैध स्थिति में रखा जाता है, कोई फर्क नहीं पड़ता कि अन्य धागे इसे कैसे एक्सेस करते हैं। परमाणु संचालन कई थ्रेड लॉकिंग तंत्रों का आधार बनता है।
अधिक पढ़ें:
http://en.wikipedia.org/wiki/Thread_safety
फ्रेंच में: http://fr.wikipedia.org/wiki/Threadsafe (बहुत कम)
थ्रेड-सुरक्षित कोड वह कोड होता है जो कई थ्रेड्स को एक साथ निष्पादित कर रहा है, भले ही वह काम करेगा।
एक अधिक जानकारीपूर्ण प्रश्न यह है कि क्या कोड थ्रेड को सुरक्षित नहीं बनाता है- और इसका उत्तर यह है कि चार शर्तें हैं जो सत्य होनी चाहिए ... निम्नलिखित कोड की कल्पना करें (और यह मशीन भाषा अनुवाद है)
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
मुझे इसकी समझ के लिए ब्रायन गोएत्ज़ के जावा कंजेरिएशन इन प्रैक्टिस की परिभाषा पसंद है
"एक वर्ग थ्रेड-सुरक्षित है यदि यह कई थ्रेड्स से एक्सेस करने पर सही ढंग से व्यवहार करता है, भले ही रनटाइम वातावरण द्वारा उन थ्रेड्स के निष्पादन का शेड्यूलिंग या इंटरलेयिंग हो, और कॉलिंग कोड के हिस्से पर कोई अतिरिक्त सिंक्रनाइज़ेशन या अन्य समन्वय के साथ। "
जैसा कि अन्य लोगों ने बताया है, थ्रेड सेफ्टी का मतलब है कि एक बार में एक से अधिक थ्रेड द्वारा उपयोग किए जाने पर कोड का एक टुकड़ा बिना त्रुटियों के काम करेगा।
यह ध्यान देने योग्य है कि यह कभी-कभी कंप्यूटर समय और अधिक जटिल कोडिंग की लागत पर आता है, इसलिए यह हमेशा वांछनीय नहीं होता है। यदि किसी वर्ग को केवल एक धागे पर सुरक्षित रूप से उपयोग किया जा सकता है, तो ऐसा करना बेहतर हो सकता है।
उदाहरण के लिए, जावा में दो वर्ग हैं जो लगभग समान हैं, StringBuffer
और StringBuilder
। अंतर यह है कि StringBuffer
थ्रेड-सुरक्षित है, इसलिए एक ही उदाहरण का StringBuffer
उपयोग एक साथ कई थ्रेड द्वारा किया जा सकता है। StringBuilder
थ्रेड-सुरक्षित नहीं है, और उन मामलों (विशाल बहुमत) के लिए एक उच्च-प्रदर्शन प्रतिस्थापन के रूप में डिज़ाइन किया गया है जब स्ट्रिंग केवल एक धागे से बनाया गया है।
इसे समझने का एक आसान तरीका है, वह कोड जो थ्रेड-सेफ़ नहीं है। वहाँ दो मुख्य मुद्दा है कि अवांछित व्यवहार करने के लिए एक लड़ी पिरोया आवेदन कर देगा।
लॉकिंग के बिना साझा किए गए चर को एक्सेस करना
इस चर को फ़ंक्शन को निष्पादित करते समय किसी अन्य थ्रेड द्वारा संशोधित किया जा सकता है। आप इसे अपने कार्य के व्यवहार के बारे में सुनिश्चित करने के लिए एक लॉकिंग तंत्र के साथ रोकना चाहते हैं। अंगूठे का सामान्य नियम कम से कम समय के लिए ताला रखना है।
साझा चर पर आपसी निर्भरता के कारण गतिरोध
यदि आपके पास दो साझा चर A और B. एक फ़ंक्शन में हैं, तो आप A को पहले लॉक करते हैं, बाद में आप B. को लॉक करते हैं। किसी अन्य फ़ंक्शन में, आप B को लॉक करना शुरू करते हैं और थोड़ी देर बाद, आप A. को लॉक करते हैं। एक संभावित गतिरोध है जहां पहला फ़ंक्शन बी के अनलॉक होने का इंतजार करेगा जब दूसरा फ़ंक्शन ए के अनलॉक होने का इंतजार करेगा। यह समस्या संभवतः आपके विकास के वातावरण में और केवल समय-समय पर नहीं होगी। इससे बचने के लिए, सभी ताले हमेशा एक ही क्रम में होने चाहिए।
हां और ना।
थ्रेड सुरक्षा केवल आपके साझा डेटा को एक बार में केवल एक थ्रेड द्वारा एक्सेस किए जाने से सुनिश्चित करने से थोड़ा अधिक है। आपको साझा डेटा तक अनुक्रमिक पहुंच सुनिश्चित करना है, जबकि एक ही समय में दौड़ की स्थिति , गतिरोध , लाइवलॉक और अतिरिक्त भुखमरी से बचना है। ।
अप्रत्याशित परिणाम जब कई थ्रेड चल रहे होते हैं तो थ्रेड-सुरक्षित कोड की आवश्यक शर्त नहीं होती है, लेकिन यह अक्सर एक उप-उत्पाद होता है। उदाहरण के लिए, आपके पास एक निर्माता-उपभोक्ता योजना हो सकती है जो एक साझा कतार, एक निर्माता धागा और कुछ उपभोक्ता धागे के साथ स्थापित हो, और डेटा प्रवाह पूरी तरह से अनुमानित हो सकता है। यदि आप अधिक उपभोक्ताओं को पेश करना शुरू करते हैं, तो आप अधिक यादृच्छिक खोज परिणाम देखेंगे।
संक्षेप में, बहु थ्रेडेड वातावरण में कई चीजें गलत हो सकती हैं (निर्देश पुन: व्यवस्थित करना, आंशिक रूप से निर्मित वस्तुएं, एक ही चर का सीपीयू स्तर पर कैशिंग के कारण विभिन्न थ्रेड्स में अलग-अलग मान होना)।
मुझे Java Concurrency द्वारा प्रैक्टिस में दी गई परिभाषा पसंद है :
[कोड का एक भाग] थ्रेड-सुरक्षित है यदि यह कई थ्रेड्स से एक्सेस करने पर सही ढंग से व्यवहार करता है, भले ही रनटाइम वातावरण द्वारा उन थ्रेड्स के निष्पादन का शेड्यूलिंग या इंटरलेयिंग, और बिना किसी अतिरिक्त सिंक्रनाइज़ेशन या अन्य समन्वय के भाग पर। कॉलिंग कोड।
द्वारा सही ढंग से वे अपनी विशिष्टताओं के अनुपालन में मतलब है कि कार्यक्रम बर्ताव करती है।
उदाहरण दिया
कल्पना कीजिए कि आप एक काउंटर लागू करते हैं। आप कह सकते हैं कि यह सही ढंग से व्यवहार करता है यदि:
counter.next()
वह मान कभी नहीं लौटाता है जो पहले ही वापस आ चुका है (हम सादगी के लिए कोई अतिप्रवाह आदि नहीं मानते हैं)एक थ्रेड सुरक्षित काउंटर उन नियमों के अनुसार व्यवहार करेगा, चाहे कितने सूत्र इसे समवर्ती रूप से एक्सेस करते हों (जो आमतौर पर एक भोले कार्यान्वयन की स्थिति नहीं होगी)।
बस - कोड ठीक चलेगा यदि कई धागे एक ही समय में इस कोड को निष्पादित कर रहे हैं।
निर्धारण के साथ धागा सुरक्षा को भ्रमित न करें। थ्रेड-सुरक्षित कोड गैर-नियतात्मक भी हो सकता है। थ्रेडेड कोड के साथ डिबगिंग समस्याओं की कठिनाई को देखते हुए, यह शायद सामान्य मामला है। :-)
थ्रेड सुरक्षा केवल यह सुनिश्चित करती है कि जब कोई थ्रेड साझा किए गए डेटा को संशोधित या पढ़ रहा है, तो कोई अन्य थ्रेड इसे उस तरीके से एक्सेस नहीं कर सकता है जो डेटा को बदलता है। यदि आपका कोड शुद्धता के लिए निष्पादन के लिए एक निश्चित आदेश पर निर्भर करता है, तो आपको इसे सुनिश्चित करने के लिए थ्रेड सुरक्षा के लिए आवश्यक अन्य सिंक्रनाइज़ेशन तंत्र की आवश्यकता होगी।
मैं अन्य अच्छे उत्तरों के शीर्ष पर कुछ और जानकारी जोड़ना चाहूंगा।
थ्रेड सुरक्षा से तात्पर्य है कि कई थ्रेड्स मेमोरी असंगति त्रुटियों के बिना एक ही ऑब्जेक्ट में डेटा लिख / पढ़ सकते हैं। अत्यधिक बहु थ्रेडेड प्रोग्राम में, थ्रेड सेफ प्रोग्राम साझा डेटा पर दुष्प्रभाव नहीं डालता है ।
अधिक जानकारी के लिए इस एसई प्रश्न पर एक नजर:
थ्रेड सेफ प्रोग्राम मेमोरी की संगति की गारंटी देता है ।
उन्नत समवर्ती एपीआई पर ओरेकल प्रलेखन पृष्ठ से :
मेमोरी संगति गुण:
जावा ™ लैंग्वेज स्पेसिफिकेशन का चैप्टर 17, मेमोरी ऑपरेशंस पर होने वाले रिलेशन को परिभाषित करता है, जैसे कि शेयर्ड वेरिएबल्स को रीड और राइट करता है। एक थ्रेड द्वारा लिखने के परिणाम को दूसरे थ्रेड द्वारा केवल पढ़ने के लिए दृश्यमान होने की गारंटी दी जाती है, यदि लेखन ऑपरेशन होता है-रीड ऑपरेशन से पहले ।
synchronized
और volatile
निर्माणों, साथ ही Thread.start()
और Thread.join()
तरीकों, कर सकते हैं प्रपत्र होता है-पहले रिश्ते।
सभी वर्गों java.util.concurrent
और इसके उप- वर्गों की विधियाँ इन गारंटियों को उच्च-स्तरीय सिंक्रनाइज़ेशन तक विस्तारित करती हैं । विशेष रूप से:
Runnable
करने के लिए एक Executor
होने से पहले इसके निष्पादन शुरू होता है। इसी तरह से Callables के लिए सबमिट किया गया a ExecutorService
।Future
परिणाम के पुनर्प्राप्ति के बाद होने वाली क्रियाओं से पहले होने वाली अतुल्यकालिक संगणना द्वारा लिया गया कार्यFuture.get()
किसी अन्य थ्रेड के ।Lock.unlock, Semaphore.release, and CountDownLatch.countDown
से पहले की कार्रवाईLock.lock, Semaphore.acquire, Condition.await, and CountDownLatch.await
एक अन्य थ्रेड में समान सिंक्रनाइज़र ऑब्जेक्ट पर।Exchanger
, से पहले की कार्रवाईexchange()
, प्रत्येक धागे में दूसरे धागे में संबंधित एक्सचेंज () के बाद होने वाले से पहले होती हैं।CyclicBarrier.await
और Phaser.awaitAdvance
(साथ ही साथ इसके वेरिएंट) भी होती हैं-बैरियर एक्शन द्वारा की जाने वाली एक्शन से पहले की जाने वाली क्रियाएँ, और एक्शन के द्वारा की जाने वाली एक्शन होती हैं-एक्शन से पहले होने वाली एक्शन के बाद अन्य थ्रेड्स में सफल होने के बाद।अन्य उत्तरों को पूरा करने के लिए:
सिंक्रनाइज़ेशन केवल एक चिंता का विषय है जब आपकी विधि में कोड दो चीजों में से एक करता है:
इसका मतलब यह है कि आपकी विधि से परिभाषित चर हमेशा थ्रेडसेफ़ हैं। एक विधि के लिए प्रत्येक कॉल में इन चरों का अपना संस्करण होता है। यदि विधि को किसी अन्य थ्रेड द्वारा, या उसी थ्रेड द्वारा कॉल किया जाता है, या यहां तक कि यदि विधि स्वयं को कॉल करती है (पुनरावर्तन), तो इन चरों के मान साझा नहीं किए जाते हैं।
थ्रेड शेड्यूलिंग को राउंड-रॉबिन होने की गारंटी नहीं है । एक कार्य पूरी तरह से एक ही प्राथमिकता के धागे की कीमत पर सीपीयू को हॉग कर सकता है। आप एक विवेक रखने के लिए Thread.yield () का उपयोग कर सकते हैं। थ्रेड की प्राथमिकता को कम करने के लिए आप (जावा में) थ्रेड.सेटपायरिटी (थ्रेड .NORM_PRIORITY-1) का उपयोग कर सकते हैं
इसके अलावा सावधान:
हाँ और हाँ। तात्पर्य यह है कि डेटा एक साथ एक से अधिक थ्रेड द्वारा संशोधित नहीं किया गया है। हालाँकि, आपका कार्यक्रम अपेक्षित रूप से काम कर सकता है, और थ्रेड-सेफ दिखाई दे सकता है, भले ही यह मौलिक रूप से न हो।
ध्यान दें कि परिणामों की अप्रत्याशितता 'रेस-कंडीशन्स' का परिणाम है, जिसके परिणामस्वरूप संभवतः डेटा को एक ऑर्डर के अलावा अन्य ऑर्डर में संशोधित किया जा सकता है।
आइए इसका उत्तर उदाहरण के तौर पर दें:
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 है और न ही सही है।
तो यह कोड थ्रेड सुरक्षित नहीं है।
संक्षेप में, सभी बहु-सूत्रण समस्याएं इस तरह की समस्या के कुछ भिन्नता के कारण होती हैं।
इसका समाधान यह सुनिश्चित करना है कि जोड़ और तुलना को अलग नहीं किया जा सकता है (उदाहरण के लिए किसी तरह के सिंक्रनाइज़ेशन कोड द्वारा दो कथनों को घेरकर) या ऐसे समाधान को तैयार करने के लिए जिसमें दो कार्यों की आवश्यकता नहीं होती है। ऐसा कोड थ्रेड-सुरक्षित होगा।
कम से कम C ++ में, मुझे लगता है थ्रेड-सेफ को एक मिथ्या नाम के रूप में कि यह नाम से बहुत कुछ छोड़ देता है। थ्रेड-सुरक्षित होने के लिए, कोड को आमतौर पर इसके बारे में सक्रिय होना पड़ता है। यह आमतौर पर एक निष्क्रिय गुणवत्ता नहीं है।
एक वर्ग को चलने के लिए सुरक्षित होने के लिए, इसमें "अतिरिक्त" विशेषताएं होनी चाहिए जो ओवरहेड को जोड़ती हैं। ये विशेषताएं वर्ग के कार्यान्वयन का हिस्सा हैं और आम तौर पर बोलना, इंटरफ़ेस से छिपा हुआ है। यही है, अलग-अलग धागे किसी भी वर्ग के सदस्यों तक पहुंच सकते हैं, कभी भी एक अलग धागे द्वारा समवर्ती पहुंच के साथ संघर्ष करने के बारे में चिंता करने के लिए और ऐसा बहुत आलसी तरीके से कर सकते हैं, सादे पुरानी नियमित मानव कोडिंग शैली का उपयोग किए बिना। सभी कि पागल तुल्यकालन सामान जो पहले से ही कोड के हिम्मत में लुढ़का हुआ है।
और यही कारण है कि कुछ लोग इस शब्द का उपयोग करना पसंद करते हैं आंतरिक रूप से सिंक्रनाइज़ ।
इन विचारों के लिए शब्दावली के तीन मुख्य सेट हैं जिनका मैंने सामना किया है। पहला और ऐतिहासिक रूप से अधिक लोकप्रिय (लेकिन बदतर) है:
दूसरा (और बेहतर) है:
एक तीसरा है:
धागा सुरक्षित ~ धागा सबूत ~ आंतरिक रूप से सिंक्रनाइज़
आंतरिक रूप से सिंक्रनाइज़ (उर्फ। थ्रेड-सेफ या थ्रेड प्रूफ ) प्रणाली का एक उदाहरण एक रेस्तरां है जहां एक मेजबान आपको दरवाजे पर स्वागत करता है, और आपको खुद को कतार में लगाने से रोकता है। मेजबान कई ग्राहकों के साथ व्यवहार करने के लिए रेस्तरां के तंत्र का हिस्सा है, और प्रतीक्षा करने वाले ग्राहकों के बैठने के अनुकूलन के लिए कुछ बल्कि मुश्किल ट्रिक्स का उपयोग कर सकता है, जैसे कि उनकी पार्टी के आकार को ध्यान में रखते हुए, या उनके पास कितना समय लगता है। , या यहां तक कि फोन पर आरक्षण लेना। रेस्तरां आंतरिक रूप से सिंक्रनाइज़ है, क्योंकि यह सभी इसके साथ बातचीत करने के लिए इंटरफ़ेस का हिस्सा है।
थ्रेड-सेफ (लेकिन अच्छा नहीं) ~ थ्रेड संगत ~ बाह्य रूप से सिंक्रनाइज़ ~ फ्री-थ्रेडेड
मान लीजिए कि आप बैंक जाते हैं। बैंक टेलर के लिए एक लाइन यानी विवाद है। क्योंकि आप एक जंगली नहीं हैं, आप समझते हैं कि किसी संसाधन के लिए विवाद के बीच सबसे अच्छी बात यह है कि एक सभ्य व्यक्ति की तरह कतार में खड़ा होना चाहिए। कोई भी तकनीकी रूप से आपको ऐसा नहीं करता है। हमें उम्मीद है कि आपके पास इसे करने के लिए आवश्यक सामाजिक प्रोग्रामिंग है। इस अर्थ में, बैंक लॉबी बाहरी रूप से सिंक्रनाइज़ है। क्या हमें यह कहना चाहिए कि यह थ्रेड-असुरक्षित है? यदि आप थ्रेड-सुरक्षित , थ्रेड-असुरक्षित द्विध्रुवी शब्दावली सेट के साथ जाते हैं तो इसका निहितार्थ क्या है । यह शब्दों का एक बहुत अच्छा सेट नहीं है। बेहतर शब्दावली है बाहरी रूप से सिंक्रनाइज़ है,बैंक लॉबी कई ग्राहकों द्वारा एक्सेस किए जाने के लिए शत्रुतापूर्ण नहीं है, लेकिन यह उन्हें सिंक्रनाइज़ करने का काम भी नहीं करता है। ग्राहक स्वयं ऐसा करते हैं।
इसे "फ्री थ्रेडेड" भी कहा जाता है, जहां "मुक्त" "जूँ से मुक्त" के रूप में है - या इस मामले में, ताले। ठीक है, और अधिक सटीक, तुल्यकालन आदिम। इसका मतलब यह नहीं है कि कोड उन आदिमों के बिना कई थ्रेड्स पर चल सकता है। इसका मतलब यह है कि यह उनके साथ पहले से ही स्थापित नहीं है और यह आप पर निर्भर है, कोड का उपयोगकर्ता, उन्हें खुद को स्थापित करने के लिए हालांकि आप फिट दिखते हैं। अपने खुद के सिंक्रनाइज़ेशन प्राइमेटिक्स को स्थापित करना कठिन हो सकता है और कोड के बारे में कठिन सोचने की आवश्यकता होती है, लेकिन यह भी आपको आज के हाइपरथ्रेडेड सीपीयू पर प्रोग्राम को निष्पादित करने की अनुमति देकर सबसे तेज संभव प्रोग्राम को जन्म दे सकता है।
थ्रेड सुरक्षित नहीं है (और खराब) ~ थ्रेड शत्रुता ~ अनसंकटनीय
थ्रेड-शत्रुतापूर्ण प्रणाली की एक रोजमर्रा की सादृश्यता कुछ झटके वाली है जिसमें स्पोर्ट्स कार अपने ब्लिंकर और गलियों को विली-निली का उपयोग करने से मना करती है। उनकी ड्राइविंग शैली थ्रेड शत्रुतापूर्ण या अस्थिर है, क्योंकि आपके पास उनके साथ समन्वय करने का कोई तरीका नहीं है, और यह बिना किसी रिज़ॉल्यूशन के एक ही लेन के लिए विवाद पैदा कर सकता है, और इस तरह एक दुर्घटना दो कारों को एक ही स्थान पर कब्जा करने का प्रयास करती है, बिना किसी प्रोटोकॉल के। इसे रोकें। इस पैटर्न को अधिक व्यापक रूप से असामाजिक के रूप में भी सोचा जा सकता है , जिसे मैं पसंद करता हूं क्योंकि यह थ्रेड्स के लिए कम विशिष्ट है और इसलिए आमतौर पर प्रोग्रामिंग के कई क्षेत्रों पर लागू होता है।
पहला और सबसे पुराना शब्दावली सेट थ्रेड शत्रुता और थ्रेड संगतता के बीच महीन भेद करने में विफल रहता है । थ्रेड संगतता तथाकथित थ्रेड सुरक्षा की तुलना में अधिक निष्क्रिय है, लेकिन इसका मतलब यह नहीं है कि तथाकथित कोड समवर्ती धागा उपयोग के लिए असुरक्षित है। इसका मतलब है कि यह सिंक्रनाइज़ेशन के बारे में निष्क्रिय है जो इसे आंतरिक कोड के भाग के रूप में प्रदान करने के बजाय इसे कॉलिंग कोड में डाल देगा। थ्रेड कम्पेटिबल है कि कैसे कोड को ज्यादातर मामलों में डिफ़ॉल्ट रूप से लिखा जाना चाहिए लेकिन यह भी दुर्भाग्य से अक्सर गलती से थ्रेड असुरक्षित के रूप में सोचा जाता है, जैसे कि यह स्वाभाविक रूप से विरोधी सुरक्षा है, जो प्रोग्रामर के लिए भ्रम का एक प्रमुख बिंदु है।
नोट: कई सॉफ्टवेयर मैनुअल वास्तव में "थ्रेड-सेफ" शब्द का उपयोग "थ्रेड-कम्पेटिबल" के रूप में करते हैं, जो पहले से ही गड़बड़ था और भी अधिक भ्रम जोड़ रहा है! मैं इस कारण से हर कीमत पर "थ्रेड-सेफ" और "थ्रेड-असुरक्षित" शब्द से बचता हूं, क्योंकि कुछ स्रोत कुछ "थ्रेड-सेफ" कहेंगे, जबकि अन्य इसे "थ्रेड-असुरक्षित" कहेंगे, क्योंकि वे सहमत नहीं हो सकते हैं इस बात पर कि आपको सुरक्षा के लिए कुछ अतिरिक्त मानकों को पूरा करना है (सिंक्रोनाइज़ेशन प्राइमेटीज़), या "सुरक्षित" माने जाने के लिए शत्रुतापूर्ण नहीं होना चाहिए। इसलिए अन्य इंजीनियरों के साथ खतरनाक गलतफहमी से बचने के लिए, उन शर्तों से बचें और इसके बजाय होशियार शर्तों का उपयोग करें।
अनिवार्य रूप से, हमारा लक्ष्य अराजकता को कम करना है।
हम ऐसा करते हैं कि निर्धारक प्रणाली बनाकर हम भरोसा कर सकते हैं। नियतत्ववाद महंगा है, ज्यादातर अवसरवाद की समानता, पाइपलाइनिंग, और रीऑर्डरिंग को खोने के कारण है। हम नियतत्ववाद की मात्रा को कम करने की कोशिश करते हैं, हमें अपनी लागत कम रखने की आवश्यकता है, साथ ही ऐसे निर्णय लेने से भी बचना चाहिए जो आगे चलकर यह तय कर सकते हैं कि हम किस छोटे निर्धारकवाद को बर्दाश्त कर सकते हैं।
थ्रेड का सिंक्रनाइज़ेशन ऑर्डर बढ़ाने और अराजकता को कम करने के बारे में है। आप जिन स्तरों पर यह करते हैं, वे ऊपर उल्लिखित शर्तों के अनुरूप हैं। उच्चतम स्तर का मतलब है कि एक प्रणाली हर बार पूरी तरह से अनुमानित तरीके से व्यवहार करती है। दूसरे स्तर का मतलब है कि सिस्टम पर्याप्त रूप से व्यवहार करता है कि कॉलिंग कोड अविश्वसनीय रूप से अप्रत्याशितता का पता लगा सकता है। उदाहरण के लिए, एक कंडीशन वेरिएबल में एक अजीब वेकअप या म्यूटेक्स को लॉक करने में विफलता क्योंकि यह तैयार नहीं है। तीसरे स्तर का मतलब है कि प्रणाली किसी और के साथ खेलने के लिए पर्याप्त व्यवहार नहीं करती है और केवल अव्यवस्था के बिना एकल-पिरोया जा सकता है।
कोड या वर्गों को धागे के रूप में सुरक्षित रखने या न करने के बारे में सोचने के बजाय , मुझे लगता है कि थ्रेड-सुरक्षित होने के रूप में कार्यों के बारे में सोचना अधिक सहायक है । दो कार्य थ्रेड सुरक्षित हैं यदि वे मनमाने ढंग से थ्रेडिंग संदर्भों से चलने पर निर्दिष्ट के रूप में व्यवहार करेंगे। कई मामलों में, कक्षाएं थ्रेड-सुरक्षित फैशन में कुछ कार्यों के संयोजन का समर्थन करेगी और अन्य नहीं।
उदाहरण के लिए, सरणी-सूचियों और हैश सेट जैसे कई संग्रह इस बात की गारंटी देंगे कि यदि उन्हें शुरू में एक धागे से विशेष रूप से एक्सेस किया जाता है, और किसी संदर्भ में किसी अन्य धागे के दिखाई देने के बाद उन्हें संशोधित नहीं किया जाता है, तो उन्हें किसी भी संयोजन द्वारा मनमाने ढंग से पढ़ा जा सकता है। हस्तक्षेप के बिना धागे के।
अधिक दिलचस्प बात यह है कि कुछ हैश-सेट संग्रह जैसे कि मूल गैर-जेनेरिक .NET में .NET, गारंटी दे सकता है कि जब तक कोई आइटम कभी भी हटाया नहीं जाता है, और बशर्ते कि केवल एक धागा उन्हें कभी भी लिखता है, कोई भी धागा जो कोशिश करता है संग्रह पढ़ना व्यवहार करेगा जैसे कि एक संग्रह तक पहुंच जहां अद्यतन में देरी हो सकती है और मनमाना क्रम में हो सकता है, लेकिन जो अन्यथा सामान्य रूप से व्यवहार करेगा। यदि थ्रेड # 1 एक्स और फिर वाई जोड़ता है, और थ्रेड # 2 के लिए देखता है और वाई और फिर एक्स को देखता है, तो थ्रेड # 2 के लिए यह देखना संभव होगा कि वाई मौजूद है लेकिन एक्स नहीं करता है; इस तरह का व्यवहार "थ्रेड-सेफ" है या नहीं, इस बात पर निर्भर करेगा कि थ्रेड # 2 उस संभावना से निपटने के लिए तैयार है या नहीं।
अंतिम नोट के रूप में, कुछ कक्षाएं - विशेष रूप से संचार पुस्तकालयों को अवरुद्ध करना - एक "करीबी" या "निपटान" विधि हो सकती है जो अन्य सभी तरीकों के संबंध में थ्रेड-सुरक्षित है, लेकिन कोई अन्य विधियां जो सम्मान के साथ थ्रेड-सुरक्षित हैं एक दूसरे। यदि कोई थ्रेड एक अवरुद्ध रीड अनुरोध करता है और प्रोग्राम का एक उपयोगकर्ता "रद्द" पर क्लिक करता है, तो उस थ्रेड द्वारा जारी किए जाने वाले नज़दीकी अनुरोध के लिए कोई रास्ता नहीं होगा जो रीड को निष्पादित करने का प्रयास कर रहा है। हालाँकि, नज़दीकी / डिस्पोज़ रिक्वेस्ट, अतुल्यकालिक रूप से एक ध्वज सेट कर सकता है जिसके कारण रीड अनुरोध जल्द से जल्द रद्द हो जाएगा। एक बार किसी भी थ्रेड को बंद करने के बाद, ऑब्जेक्ट बेकार हो जाएगा, और भविष्य के कार्यों में सभी प्रयास तुरंत विफल हो जाएंगे;