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


124

हाल ही में मैंने एक टेक्स्ट बॉक्स को थ्रेड (UI थ्रेड के अलावा) से एक्सेस करने की कोशिश की और एक अपवाद फेंक दिया गया। इसने "कोड थ्रेड सेफ नहीं होने" के बारे में कुछ कहा और इसलिए मैंने एक डेलीगेट (MSDN से नमूना मदद की) लिखना और इसके बजाय इसे कॉल करना समाप्त कर दिया।

लेकिन फिर भी मुझे समझ में नहीं आया कि सभी अतिरिक्त कोड क्यों आवश्यक थे।

अद्यतन: यदि मैं जाँच करूँ तो क्या मैं किसी गंभीर समस्या में भाग जाऊंगा

Controls.CheckForIllegalCrossThread..blah =true

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

7
डुप्लिकेट ?: stackoverflow.com/questions/261683/…
डेव ओ।

@ क्षमा करें मैंने खोज करने की कोशिश की, लेकिन छोड़ दिया ... धन्यवाद वैसे भी ..
विवेक बर्नार्ड

1
एक कोड जो उत्पन्न नहीं होता हैRace-Condition
मुहम्मद बाबर

जवाबों:


121

एरिक लिपर्ट का एक अच्छा ब्लॉग पोस्ट है जिसका शीर्षक है कि आप इस चीज़ को "थ्रेड सेफ" कहते हैं? विकिपीडिया के अनुसार थ्रेड सुरक्षा की परिभाषा के बारे में।

लिंक से निकाली गई 3 महत्वपूर्ण बातें:

"कोड का एक टुकड़ा थ्रेड-सुरक्षित है यदि यह एक साथ कई थ्रेड द्वारा निष्पादन के दौरान सही ढंग से कार्य करता है।"

"विशेष रूप से, इसे एक ही साझा किए गए डेटा तक पहुँचने के लिए कई थ्रेड्स की आवश्यकता को पूरा करना होगा ..."

"... और किसी भी समय केवल एक थ्रेड द्वारा एक्सेस किए जाने वाले डेटा के साझा टुकड़े की आवश्यकता।"

निश्चित रूप से पढ़ने लायक!


25
कृपया लिंक को केवल उत्तरों से बचें क्योंकि यह भविष्य में कभी भी खराब हो सकता है।
akhil_mittal


106

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


11
इसे सिंक्रनाइजेशन कहा जाता है। सही?
JavaTechnical

3
हाँ। एक साझा संसाधन तक पहुंचने के लिए प्रतीक्षा करने के लिए विभिन्न थ्रेड्स को मजबूर करना सिंक्रनाइज़ेशन के साथ पूरा किया जा सकता है।
विंसेंट रामधनी

ग्रेगोरी के स्वीकृत उत्तर से, वह कह रहा है "" कोड का एक टुकड़ा थ्रेड-सुरक्षित है यदि यह कई थ्रेड्स के साथ-साथ निष्पादन के दौरान सही ढंग से कार्य करता है। " जब आप कह रहे हैं "तब इसे सुरक्षित रखने के लिए, आपको 1 व्यक्ति को प्रतीक्षा करने के लिए मजबूर करना होगा", क्या वह यह कहते हुए साथ में स्वीकार्य नहीं है कि आप यह नहीं कह रहे हैं? क्या आप कृपया समझा सकते हैं?
Honey

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

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

18

विकिपीडिया में थ्रेड सेफ्टी पर एक लेख है।

यह परिभाषा पृष्ठ (आपको एक विज्ञापन छोड़ना होगा - क्षमा करें) इसे इस प्रकार परिभाषित करता है:

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

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

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

जैसा कि इन थ्रेड्स को अक्सर सामान्य क्रियाएं करने की आवश्यकता होती है - डिस्क i / o, स्क्रीन पर आउटपुट परिणाम आदि - कोड के इन हिस्सों को इस तरह से लिखना होगा कि वे कई थ्रेड्स से बुलाए जा सकते हैं, अक्सर उसी समय। इसमें निम्न शामिल होंगे:

  • डेटा की प्रतियों पर काम करना
  • महत्वपूर्ण कोड के चारों ओर ताले जोड़ना

8

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

निम्नलिखित विधि पर विचार करें:

private int myInt = 0;
public int AddOne()
{
    int tmp = myInt;
    tmp = tmp + 1;
    myInt = tmp;
    return tmp;
}

अब थ्रेड A और थ्रेड B दोनों AddOne () को निष्पादित करना चाहेंगे। लेकिन A पहले शुरू होता है और myInt (0) के मान को tmp में पढ़ता है। अब किसी कारण से शेड्यूलर ने थ्रेड ए को रोक दिया और बी बी थ्रेड बी के लिए निष्पादन को स्थगित कर दिया। अब myInt (अभी भी 0) के मूल्य को स्वयं के वैरिएबल tmp में पढ़ता है। थ्रेड बी पूरी विधि को पूरा करता है, इसलिए अंत में myInt = 1. और 1 को लौटा दिया जाता है। अब थ्रेड ए की बारी है। थ्रेड ए जारी है। और 1 से tmp को जोड़ता है (tmp था 0 थ्रेड ए के लिए)। और फिर इस मान को myInt में सहेजता है। myInt फिर से 1 है।

तो इस मामले में विधि AddOne को दो बार बुलाया गया था, लेकिन क्योंकि विधि को थ्रेड में लागू नहीं किया गया था सुरक्षित तरीके से myInt का मान 2 नहीं है, जैसा कि अपेक्षित था, लेकिन 1 क्योंकि दूसरे थ्रेड ने वैरिएबल myInt को पढ़ा है पहले थ्रेड समाप्त होने से पहले इसे अपडेट कर रहा है।

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


अगर विधि AddOne को दो बार बुलाया गया
सुजीत PS

6

वास्तविक दुनिया में आम आदमी के लिए उदाहरण है

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

थ्रेडसेफ़ का अर्थ है कि एक वस्तु की स्थिति नहीं बदलती है अगर एक साथ कई धागे वस्तु तक पहुंचने की कोशिश करते हैं।


5

आप "प्रैक्टिस में जावा कॉन्सिक्वेंसी" पुस्तक से अधिक स्पष्टीकरण प्राप्त कर सकते हैं:

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


4

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

यहां, एक मॉड्यूल डेटा-संरचना, वर्ग, वस्तु, विधि / प्रक्रिया या कार्य हो सकता है। मूल रूप से कोड और संबंधित डेटा का टुकड़ा।

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

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

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


3

थ्रेड सेफ्टी : थ्रेड सेफ प्रोग्राम मेमोरी प्रोटेक्शन एरर से डेटा को सुरक्षित रखता है। एक उच्च बहु-थ्रेडेड प्रोग्राम में, थ्रेड सेफ प्रोग्राम एक ही ऑब्जेक्ट पर कई थ्रेड्स से कई रीड / राइट ऑपरेशन के साथ कोई साइड इफेक्ट नहीं करता है। विभिन्न थ्रेड्स में स्थिरता त्रुटियों के बिना ऑब्जेक्ट डेटा को साझा और संशोधित किया जा सकता है।

आप उन्नत संगामिति API का उपयोग करके थ्रेड सुरक्षा प्राप्त कर सकते हैं। यह प्रलेखन पृष्ठ थ्रेड सुरक्षा प्राप्त करने के लिए अच्छे प्रोग्रामिंग कंस्ट्रक्शन प्रदान करता है।

लॉक ऑब्जेक्ट्स लॉकिंग मुहावरों का समर्थन करते हैं जो कई समवर्ती अनुप्रयोगों को सरल बनाते हैं।

निष्पादकों शुरू करने और धागे के प्रबंधन के लिए एक उच्च स्तरीय एपीआई परिभाषित करते हैं। Java.util.concurrent द्वारा प्रदान किए गए निष्पादन कार्यान्वयन बड़े पैमाने के अनुप्रयोगों के लिए उपयुक्त थ्रेड पूल प्रबंधन प्रदान करते हैं।

समवर्ती संग्रह डेटा के बड़े संग्रह को प्रबंधित करना आसान बनाते हैं, और सिंक्रनाइज़ेशन की आवश्यकता को बहुत कम कर सकते हैं।

परमाणु चर में ऐसी विशेषताएं होती हैं जो सिंक्रनाइज़ेशन को कम करती हैं और मेमोरी संगति त्रुटियों से बचने में मदद करती हैं।

थ्रेडलोकल्रैंडम (JDK 7 में) कई थ्रेड्स से कुशल जेनरेशन की छद्म संख्या प्रदान करता है।

अन्य प्रोग्रामिंग कंस्ट्रक्शन के लिए java.util.concurrent और java.util.concurrent.atomic पैकेज देखें ।


1

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

सामान्य WinForms अभ्यास एक एकल धागा है जो आपके सभी UI कार्य के लिए समर्पित है।


1

मुझे http://en.wikipedia.org/wiki/Reentrancy_%28computing%29 की अवधारणा ऐसी लगती है जो मैं आमतौर पर असुरक्षित थ्रेडिंग के रूप में सोचता हूं, जब एक विधि होती है और एक वैश्विक चर जैसे साइड इफेक्ट पर निर्भर करती है।

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

//built in global set to locale specific value (here a comma)
decimalSeparator = ','

function FormatDot(value : real):
    //save the current decimal character
    temp = decimalSeparator

    //set the global value to be 
    decimalSeparator = '.'

    //format() uses decimalSeparator behind the scenes
    result = format(value)

    //Put the original value back
    decimalSeparator = temp

-2

थ्रेड सुरक्षा को समझने के लिए, नीचे दिए गए सेक्शन पढ़ें :

4.3.1। उदाहरण: वाहन ट्रैकर प्रतिनिधि का उपयोग करना

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

लिस्टिंग 4.6। DeutatingVehicleTracker द्वारा उपयोग किए जाने वाले अपरिवर्तनीय बिंदु वर्ग।

 class Point{
  public final int x, y;

  public Point() {
        this.x=0; this.y=0;
    }

  public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

}

Pointथ्रेड-सुरक्षित है क्योंकि यह अपरिवर्तनीय है। अपरिवर्तनीय मूल्यों को स्वतंत्र रूप से साझा और प्रकाशित किया जा सकता है, इसलिए हमें उन्हें वापस करते समय स्थानों को कॉपी करने की आवश्यकता नहीं है।

DelegatingVehicleTracker4.7 को सूचीबद्ध करने में किसी भी स्पष्ट तुल्यकालन का उपयोग नहीं किया जाता है; राज्य तक सभी पहुंच का प्रबंधन किया जाता है ConcurrentHashMap, और मानचित्र की सभी कुंजी और मूल्य अपरिवर्तनीय हैं।

लिस्टिंग 4.7। एक कॉन्ट्रैक्टहैश मैप में थ्रेड सेफ्टी को डेलिगेट करना।

  public class DelegatingVehicleTracker {

  private final ConcurrentMap<String, Point> locations;
    private final Map<String, Point> unmodifiableMap;

  public DelegatingVehicleTracker(Map<String, Point> points) {
        this.locations = new ConcurrentHashMap<String, Point>(points);
        this.unmodifiableMap = Collections.unmodifiableMap(locations);
    }

  public Map<String, Point> getLocations(){
        return this.unmodifiableMap; // User cannot update point(x,y) as Point is immutable
    }

  public Point getLocation(String id) {
        return locations.get(id);
    }

  public void setLocation(String id, int x, int y) {
        if(locations.replace(id, new Point(x, y)) == null) {
             throw new IllegalArgumentException("invalid vehicle name: " + id);
        }
    }

}

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

4.3.2। स्वतंत्र राज्य चर

हम थ्रेड सेफ्टी को एक से अधिक अंतर्निहित स्टेट वैरिएबल में भी सौंप सकते हैं, जब तक कि उन अंतर्निहित स्टेट वैरिएबल स्वतंत्र होते हैं, जिसका अर्थ है कि कंपोजिट क्लास कई स्टेट वैरिएबल को शामिल करने वाले किसी भी इंवेरिएंट को लागू नहीं करता है।

VisualComponentलिस्टिंग ४.१ में एक चित्रमय घटक है जो ग्राहकों को माउस और कीस्ट्रोक घटनाओं के लिए श्रोताओं को पंजीकृत करने की अनुमति देता है। यह प्रत्येक प्रकार के पंजीकृत श्रोताओं की एक सूची रखता है, ताकि जब कोई घटना घटित हो तो उपयुक्त श्रोताओं को आमंत्रित किया जा सके। लेकिन माउस श्रोताओं और प्रमुख श्रोताओं के सेट के बीच कोई संबंध नहीं है; दो स्वतंत्र हैं, और इसलिए VisualComponentदो अंतर्निहित थ्रेड-सुरक्षित सूचियों के लिए अपने थ्रेड सुरक्षा दायित्वों को सौंप सकते हैं।

लिस्टिंग 4.9। कई अंतर्निहित राज्य चर के लिए थ्रेडिंग सुरक्षा को डेलिगेट करना।

public class VisualComponent {
    private final List<KeyListener> keyListeners 
                                        = new CopyOnWriteArrayList<KeyListener>();
    private final List<MouseListener> mouseListeners 
                                        = new CopyOnWriteArrayList<MouseListener>();

  public void addKeyListener(KeyListener listener) {
        keyListeners.add(listener);
    }

  public void addMouseListener(MouseListener listener) {
        mouseListeners.add(listener);
    }

  public void removeKeyListener(KeyListener listener) {
        keyListeners.remove(listener);
    }

  public void removeMouseListener(MouseListener listener) {
        mouseListeners.remove(listener);
    }

}

VisualComponentCopyOnWriteArrayListप्रत्येक श्रोता सूची को संग्रहीत करने के लिए एक का उपयोग करता है ; यह श्रोता-सूचियों के प्रबंधन के लिए विशेष रूप से अनुकूल एक थ्रेड-सुरक्षित सूची कार्यान्वयन है (धारा 5.2.3 देखें)। प्रत्येक सूची थ्रेड-सुरक्षित है, और क्योंकि एक के राज्य को दूसरे के राज्य में युग्मित करने में कोई बाधा नहीं VisualComponentहै, अंतर्निहित mouseListenersऔर keyListenersवस्तुओं के लिए अपनी थ्रेड सुरक्षा जिम्मेदारियों को सौंप सकते हैं।

4.3.3। जब प्रत्यायोजन विफल हो जाता है

अधिकांश मिश्रित वर्ग उतने सरल नहीं होते हैं VisualComponent: उनके पास ऐसे घटक होते हैं जो उनके घटक अवस्था चर से संबंधित होते हैं। NumberRangeलिस्टिंग में 4.10 AtomicIntegersअपने राज्य का प्रबंधन करने के लिए दो का उपयोग करता है , लेकिन एक अतिरिक्त बाधा लगाता है - कि पहली संख्या दूसरी से कम या उसके बराबर हो।

लिस्टिंग 4.10। संख्या रेंज वर्ग जो पर्याप्त रूप से अपने आक्रमणकारियों की रक्षा नहीं करता है। यह मत करो।

public class NumberRange {

  // INVARIANT: lower <= upper
    private final AtomicInteger lower = new AtomicInteger(0);
    private final AtomicInteger upper = new AtomicInteger(0);

  public void setLower(int i) {
        //Warning - unsafe check-then-act
        if(i > upper.get()) {
            throw new IllegalArgumentException(
                    "Can't set lower to " + i + " > upper ");
        }
        lower.set(i);
    }

  public void setUpper(int i) {
        //Warning - unsafe check-then-act
        if(i < lower.get()) {
            throw new IllegalArgumentException(
                    "Can't set upper to " + i + " < lower ");
        }
        upper.set(i);
    }

  public boolean isInRange(int i){
        return (i >= lower.get() && i <= upper.get());
    }

}

NumberRangeहै धागा सुरक्षित नहीं ; यह उस अपरिपक्व को संरक्षित नहीं करता है जो कम और ऊपरी को संकुचित करता है। setLowerऔर setUpperतरीकों इस अपरिवर्तनीय का प्रयास करते हैं, लेकिन ऐसा खराब करते हैं। दोनों setLowerऔर setUpperजांच तत्कालीन अधिनियम दृश्यों हैं, लेकिन वे पर्याप्त लॉकिंग का उपयोग नहीं करते उन्हें परमाणु बनाने के लिए। यदि संख्या सीमा रखती है (0, 10), और एक थ्रेड कॉल setLower(5)करता है setUpper(4), जबकि दूसरा थ्रेड कॉल करता है , कुछ अशुभ समय के साथ दोनों बसने वालों में चेक पास करेंगे और दोनों संशोधन लागू होंगे। नतीजा यह है कि रेंज अब (5, 4) रखती है - एक अमान्य स्थिति । इसलिए जबकि अंतर्निहित परमाणुइंटर थ्रेड सुरक्षित हैं, समग्र वर्ग नहीं है । क्योंकि अंतर्निहित अवस्था चर lowerऔरupperस्वतंत्र नहीं हैं, NumberRangeकेवल थ्रेड-सेफ्टी स्टेट वैरिएबल पर थ्रेड सेफ्टी को डेलिगेट नहीं कर सकते हैं।

NumberRangeअपने आक्रमणकारियों को बनाए रखने के लिए लॉकिंग का उपयोग करके धागे को सुरक्षित बनाया जा सकता है, जैसे कि एक सामान्य लॉक के साथ निचले और ऊपरी की रखवाली। ग्राहकों को अपने आक्रमणकारियों को कम करने से रोकने के लिए निचले और ऊपरी प्रकाशन से भी बचना चाहिए।

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

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

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