मुझे जावा में एटॉमिक बुलियन का उपयोग करने की आवश्यकता कब है?


जवाबों:


244

जब बूलियन की जांच और बदलने के लिए कई थ्रेड्स की आवश्यकता होती है। उदाहरण के लिए:

if (!initialized) {
   initialize();
   initialized = true;
}

यह धागा-सुरक्षित नहीं है। आप इसका उपयोग करके इसे ठीक कर सकते हैं AtomicBoolean:

if (atomicInitialized.compareAndSet(false, true)) {
    initialize();
}

51
यह एक वास्तविक दुनिया उदाहरण की तरह नहीं दिखता है - trueजब initialize()पूरा नहीं हुआ है तो अन्य धागा देख सकते हैं । इसलिए, यह केवल तभी काम करता है जब अन्य सूत्र पूरा होने की परवाह नहीं करते हैं initialize()
a

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

14
initStarted और initCompleted के लिए आपको 2 बूलियन्स की आवश्यकता होगी, फिर पहले थ्रेड को initStarted पर सेट करता है और इनिशियलाइज़ () कॉल करता है, जब तक initCompleted सत्य नहीं होता तब तक प्रतीक्षा करें।
मार्टिन

3
@Bozho - बूलियन फ़ील्ड्स को पढ़ना और लिखना परमाणु अधिकार है ?, अब, अस्थिर मुझे बूलियन फ़ील्ड का नवीनतम मूल्य देता है। तो, प्रभावी रूप से, के volatile booleanरूप में ही नहीं होगा AtomicBoolean?
TheLostMind

2
@ मॉर्टिन: बूलियन के सच होने का इंतजार करने का कोई सीधा तरीका नहीं है; आपको अतिरिक्त तंत्र की आवश्यकता है। सबसे समझदार दृष्टिकोण एक synchronizedब्लॉक का उपयोग करना है, जिस स्थिति में आपको अब AtomicBooleanए की जरूरत नहीं है , बस ए volatile boolean। ( if(! this.initialized) { synchronized(this) { if(! this.initialized) { initialize(); this.initialized = true; } } }यह सुनिश्चित करेगा कि केवल एक थ्रेड कॉल initialize, और यह कि अन्य सभी धागे इसके लिए प्रतीक्षा करते हैं, बशर्ते कि initializedचिह्नित किया गया हो volatile।)
23

52

यहाँ नोट्स ( ब्रायन गोएट्ज़ पुस्तक से ) मैंने बनाया है, जो आपकी मदद कर सकता है

AtomicXXX की कक्षाएं

  • गैर-अवरोधक तुलना-और-स्वैप कार्यान्वयन प्रदान करें

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

  • न केवल बेहतर थ्रूपुट की पेशकश करते हैं, बल्कि वे गतिरोध और प्राथमिकता के उलट के रूप में लाइनिंग की समस्याओं के लिए अधिक प्रतिरोध प्रदान करते हैं।


34

दो मुख्य कारण हैं कि आप एक परमाणु बूलियन का उपयोग क्यों कर सकते हैं। पहले इसकी उत्परिवर्तन, आप इसे एक संदर्भ के रूप में पारित कर सकते हैं और मूल्य बदल सकते हैं जो बूलियन से जुड़ा हुआ है, उदाहरण के लिए।

public final class MyThreadSafeClass{

    private AtomicBoolean myBoolean = new AtomicBoolean(false);
    private SomeThreadSafeObject someObject = new SomeThreadSafeObject();

    public boolean doSomething(){
         someObject.doSomeWork(myBoolean);
         return myBoolean.get(); //will return true
    }
}

और someObject क्लास में

public final class SomeThreadSafeObject{
    public void doSomeWork(AtomicBoolean b){
        b.set(true);
    }
}

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


4
ईश्वर के प्रेम के लिए, वह केवल वस्तु की परिवर्तनशीलता को दर्शाने के लिए था। मैंने विशेष रूप से लिखा है कि प्रदर्शन प्रयोजनों के लिए।
जॉन विंट

और आगे, अगर यह सब हो रहा था तो हाँ, यह हमेशा सच होगा
जॉन विन

यह साबित नहीं हो रहा है कि यह या isn थ्रेड-सुरक्षित है। मैं कक्षा को बहुत सुरक्षित बनाने के लिए कोड के अपने स्निपेट को समाप्त कर सकता हूं, लेकिन यह केवल मेरी बात को मारता है।
जॉन विंट

1
मुझे लगता है कि केवल वोलेटाइल पर्याप्त नहीं है। ऐसी स्थिति के बारे में सोचें जिसमें दो धागे मुख्य स्मृति से सीधे एक ही मूल्य को पढ़ते और लिखते हैं, उन थ्रेड्स के बीच कोई सिंक नहीं है - हैंस कंफर्ट प्रॉब्लम उत्पन्न हो सकती है।
Shay Tsadok

1
आप सही हैं कि यह परमाणु सेट के लिए पर्याप्त नहीं होगा, फिर ऑपरेशन की जांच करें, हालांकि ओपी से उस धारणा को बनाने के लिए पर्याप्त संदर्भ नहीं था। कहने के लिए, अस्थिर पर्याप्त नहीं हो सकता है हमेशा पाठ्यक्रम की स्थिति के आधार पर सच है।
जॉन विंट

18

AtomicBooleanवर्ग आप एक बूलियन मान कि आप atomically अद्यतन कर सकते हैं देता है। बूलियन वैरिएबल तक पहुंचने वाले कई थ्रेड्स का उपयोग करने पर इसका उपयोग करें।

Java.util.concurrent.atomic पैकेज सिंहावलोकन तुम क्या इस पैकेज में कक्षाएं करते हैं और जब उन्हें इस्तेमाल करने का एक अच्छा उच्च स्तरीय विवरण देता है। मैं ब्रायन गोएत्ज़ की पुस्तक जावा कॉन्सेप्टरी इन प्रैक्टिस भी सुझाऊँगा ।


5

पैकेज विवरण से अंश

पैकेज java.util.concurrent.atomic विवरण: कक्षाओं का एक छोटा टूलकिट जो एकल चर पर लॉक-फ्री थ्रेड-सुरक्षित प्रोग्रामिंग का समर्थन करता है। [...]

इन विधियों के विनिर्देशन कुशल मशीन-स्तरीय परमाणु निर्देशों को लागू करने में सक्षम बनाते हैं जो समकालीन प्रोसेसर पर उपलब्ध हैं। [...]

कक्षाओं के उदाहरण AtomicBoolean, AtomicInteger, AtomicLong, और AtomicReference प्रत्येक संबंधित प्रकार के एकल चर तक पहुंच और अद्यतन प्रदान करते हैं। [...]

परमाणुओं के अभिगम और अद्यतन के लिए स्मृति प्रभाव आम तौर पर वाष्पशील के नियमों का पालन करते हैं:

  • एक अस्थिर चर को पढ़ने के स्मृति प्रभाव प्राप्त होते हैं।
  • सेट में वाष्पशील चर लिखने (असाइन करने) का मेमोरी इफेक्ट होता है।
  • कमजोरकंपनीएंडसेट एटोमिकली पढ़ता है और सशर्त रूप से एक चर लिखता है, उस चर पर अन्य मेमोरी ऑपरेशन के संबंध में आदेश दिया जाता है, लेकिन अन्यथा एक साधारण गैर-वाष्पशील मेमोरी ऑपरेशन के रूप में कार्य करता है।
  • ComparAndSet और अन्य सभी रीड-एंड-अपडेट ऑपरेशन जैसे getAndIncrement में वाष्पशील चर को पढ़ने और लिखने दोनों की स्मृति प्रभाव होता है।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.