वाष्पशील बूलियन बनाम एटॉमिक बुलियन


244

एटॉमिक बुलियन क्या करता है कि एक अस्थिर बूलियन प्राप्त नहीं कर सकता है?


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


वाष्पशील बूलियन को दौड़ की स्थिति को संभालने के लिए स्पष्ट सिंक्रनाइज़ेशन की आवश्यकता होगी, दूसरे शब्दों में, साझा किए गए संसाधन जैसे अद्यतन (राज्य का परिवर्तन) कई थ्रेड्स जैसे कि वृद्धि / गिरावट काउंटर या फ़्लिपिंग बूलियन।
sactiw

जवाबों:


99

वे बिलकुल अलग हैं। volatileपूर्णांक के इस उदाहरण पर विचार करें :

volatile int i = 0;
void incIBy5() {
    i += 5;
}

यदि दो थ्रेड्स फ़ंक्शन को समवर्ती रूप से कहते हैं i, तो बाद में 5 हो सकते हैं, क्योंकि संकलित कोड कुछ इसी तरह होगा (इसके अलावा आप सिंक्रनाइज़ नहीं कर सकते हैं int):

void incIBy5() {
    int temp;
    synchronized(i) { temp = i }
    synchronized(i) { i = temp + 5 }
}

यदि एक चर अस्थिर है, तो इसके लिए प्रत्येक परमाणु पहुंच सिंक्रनाइज़ है, लेकिन यह हमेशा स्पष्ट नहीं होता है कि वास्तव में परमाणु पहुंच के रूप में क्या योग्य है। एक Atomic*वस्तु के साथ , यह गारंटी है कि प्रत्येक विधि "परमाणु" है।

इस प्रकार, यदि आप का उपयोग एक AtomicIntegerऔर getAndAdd(int delta), आप यह सुनिश्चित करें कि परिणाम होगा हो सकता है 10। उसी तरह, यदि दो थ्रेड्स एक booleanचर को समवर्ती रूप से नकारते हैं, तो AtomicBooleanआप यह सुनिश्चित कर सकते हैं कि इसका मूल मान बाद में है, ए के साथ volatile boolean, आप नहीं कर सकते।

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

का उद्देश्य volatileएक अलग है। इस उदाहरण पर विचार करें

volatile boolean stop = false;
void loop() {
    while (!stop) { ... }
}
void stop() { stop = true; }

यदि आपके पास एक थ्रेड रनिंग loop()और दूसरा थ्रेड कॉलिंग है stop(), तो आप एक लूप में भाग सकते हैं यदि आप छोड़ते हैं volatile, क्योंकि पहला थ्रेड स्टॉप के मूल्य को कैश कर सकता है। यहाँ, volatileसंकलक के साथ थोड़ा और अधिक सावधान रहने के लिए संकलक को संकेत के रूप में कार्य करता है।


84
-1: आप उदाहरण दे रहे हैं लेकिन वास्तव में एक वाष्पशील और एक एटोमिकएक्सएक्सएक्सएक्सएक्स के बीच अंतर को नहीं समझा रहे हैं।
जेसन एस

70
सवाल यह नहीं है volatile। सवाल volatile booleanबनाम के बारे में है AtomicBoolean
डोलमेन

26
-1: विशेष रूप से बूलियन के बारे में पूछे गए प्रश्न, जो अन्य डेटा प्रकारों की तुलना में एक अनूठा मामला है और इसे सीधे समझाया जाना चाहिए।
जॉन Haager

8
@ sgp15 इसे जावा 5. के तुल्यकालन के साथ करना है
मैन ऑफ वन वे

6
यदि बूलियन मान को कई थ्रेड्स द्वारा पढ़ा जाता है, लेकिन केवल एक थ्रेड द्वारा लिखा जाता है, तो volatile booleanपर्याप्त है। यदि कई लेखक भी हैं, तो आपको आवश्यकता हो सकती है AtomicBoolean
StvnBrkdll

263

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

परमाणु वर्गों की एक सूची के लिए java.util.concurrent.atomic पैकेज के JavaDocs की जाँच करें और वे कैसे काम करते हैं (सिर्फ यह सीखा कि वे लॉक-फ्री हैं, इसलिए उन्हें ताले या सिंक्रनाइज़ किए गए ब्लॉक पर एक फायदा है) का एक उत्कृष्ट विवरण है


1
@ मुझे लगता है कि @teto यह वर्णन करना चाहता है कि यदि केवल एक धागा booleanvar को संशोधित करता है , तो हमें चुनना चाहिए volatile boolean
znlyj

2
बहुत बढ़िया सारांश।
रवींद्र बाबू

56

आप ऐसा नहीं कर सकते compareAndSet, getAndSetअस्थिर बूलियन साथ परमाणु आपरेशन के रूप में (बेशक जब तक आप इसे सिंक्रनाइज़)।


6
यह सच है, लेकिन यह एक बूलियन के लिए एक बहुत दुर्लभ आवश्यकता नहीं होगी?
रॉबिन

1
@ रॉबिन एक इनिशियलाइज़ेशन विधि के एक आलसी आह्वान को नियंत्रित करने के लिए इसका उपयोग करने के बारे में सोचते हैं।
उस्मान संगत

वास्तव में मुझे लगता है कि यह मुख्य उपयोग मामलों में से एक है।
fool4jesus

42

AtomicBooleanऐसी विधियाँ हैं जो अपने यौगिक कार्यों को परमाणु रूप से करती हैं और बिना किसी synchronizedब्लॉक का उपयोग किए । दूसरी ओर, volatile booleanकेवल कंपाउंड ऑपरेशन कर सकते हैं यदि ऐसा किसी synchronizedब्लॉक के भीतर किया जाए ।

पढ़ने / लिखने के स्मृति प्रभाव क्रमशः और विधियों के volatile booleanसमान हैं।getsetAtomicBoolean

उदाहरण के लिए compareAndSetविधि निम्नलिखित रूप से (बिना किसी synchronizedखंड के) प्रदर्शन करेगी :

if (value == expectedValue) {
    value = newValue;
    return true;
} else {
    return false;
}

इसलिए, compareAndSetविधि आपको एक बार कोड लिखने की गारंटी देगी जो कि केवल एक बार निष्पादित करने की गारंटी है, यहां तक ​​कि कई थ्रेड्स से भी कॉल किया जाता है। उदाहरण के लिए:

final AtomicBoolean isJobDone = new AtomicBoolean(false);

...

if (isJobDone.compareAndSet(false, true)) {
    listener.notifyJobDone();
}

केवल एक बार श्रोता को सूचित करने की गारंटी है (कोई अन्य धागा सेट होने के बाद फिर से AtomicBooleanवापस falseसेट करता है true)।


14

volatileकीवर्ड की गारंटी होती है-उस चर को साझा करने वाले थ्रेड्स के बीच संबंध होने से पहले। यह आपको गारंटी नहीं देता है कि उस बूलियन चर का उपयोग करते समय 2 या अधिक धागे एक दूसरे को बाधित नहीं करेंगे।


14
बूलियन (आदिम प्रकार में) पहुंच जावा में परमाणु है। दोनों पढ़ते हैं और असाइनमेंट करते हैं। तो कोई अन्य धागा बूलियन ऑपरेशन को "बाधित" नहीं करेगा।
मैकीज बिलास

1
मुझे क्षमा करें लेकिन यह प्रश्न का उत्तर कैसे देता है? एक Atomic*वर्ग एक volatileक्षेत्र को लपेटता है ।
ग्रे

सीपीयू अस्थिर स्थापित करने के लिए मुख्य कारक नहीं है? यह सुनिश्चित करने के लिए कि पढ़ा गया मूल्य वास्तव में वह क्या है जो सबसे हाल ही में सेट किया गया था
१४:५१ पर ११'१

8

वाष्पशील बूलियन बनाम एटॉमिक बुलियन

परमाणु * वर्ग एक ही प्रकार के एक अस्थिर आदिम को लपेटते हैं। स्रोत से:

public class AtomicLong extends Number implements java.io.Serializable {
   ...
   private volatile long value;
   ...
   public final long get() {
       return value;
   }
   ...
   public final void set(long newValue) {
       value = newValue;
   }

इसलिए यदि आप सब कर रहे हैं और एक परमाणु स्थापित कर रहे हैं * तो आप के बजाय बस एक अस्थिर क्षेत्र हो सकता है।

एटॉमिक बुलियन क्या करता है कि एक अस्थिर बूलियन प्राप्त नहीं कर सकता है?

परमाणु * कक्षाएं आपको ऐसे तरीके देती हैं जो अधिक उन्नत कार्यक्षमता प्रदान करते हैं incrementAndGet(), जैसे कि , compareAndSet()और अन्य जो लॉकिंग के बिना कई ऑपरेशन (प्राप्त / वृद्धि / सेट, परीक्षण / सेट) लागू करते हैं। इसीलिए परमाणु * वर्ग इतने शक्तिशाली हैं।

उदाहरण के लिए, यदि एकाधिक थ्रेड्स निम्न कोड का उपयोग कर उपयोग कर रहे हैं, तो ++दौड़ की स्थिति होगी क्योंकि ++वास्तव में है: प्राप्त करें, वृद्धि, और सेट करें।

private volatile value;
...
// race conditions here
value++;

हालाँकि, निम्न कोड ताले के बिना सुरक्षित रूप से एक बहु-थ्रेडेड वातावरण में काम करेगा:

private final AtomicLong value = new AtomicLong();
...
value.incrementAndGet();

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


5

यदि क्लास स्तर के चर तक पहुंचने वाले कई धागे हैं, तो प्रत्येक धागा अपने थ्रेडलोकल कैश में उस चर की प्रतिलिपि रख सकता है।

वेरिएबल को अस्थिर बनाने से थ्रेड्स की प्रतिलिपि को थ्रेडलोकल कैश में रखने से रोका जा सकेगा।

परमाणु चर अलग-अलग होते हैं और वे अपने मूल्यों के परमाणु संशोधन की अनुमति देते हैं।


4

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

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


3

याद रखें IDIOM -

READ - MODIFY- इसे आप अस्थिरता के साथ प्राप्त नहीं कर सकते


2
छोटा, कुरकुरा और बिंदु तक। volatileकेवल उन मामलों में काम करता है जहां मालिक थ्रेड में फ़ील्ड मान को अद्यतन करने की क्षमता है और अन्य थ्रेड केवल पढ़ सकते हैं।
चाकलादेर असफाक आरव

3

यदि आपके पास अपने बूलियन को संशोधित करने वाला केवल एक धागा है, तो आप एक अस्थिर बूलियन का उपयोग कर सकते हैं (आमतौर पर आप इसे परिभाषित करने के लिए ऐसा करते हैंstop थ्रेड के मुख्य लूप में जाँच की गई चर )।

हालांकि, यदि आपके पास बूलियन को संशोधित करने वाले कई सूत्र हैं, तो आपको एक का उपयोग करना चाहिए AtomicBoolean। और, निम्न कोड सुरक्षित नहीं है:

boolean r = !myVolatileBoolean;

यह ऑपरेशन दो चरणों में किया जाता है:

  1. बूलियन मान पढ़ा जाता है।
  2. बूलियन मूल्य लिखा है।

एक अन्य धागे के बीच मूल्य को संशोधित करते हैं #1और 2#, आप एक गलत परिणाम मिला हो सकता है। AtomicBooleanविधियाँ इस समस्या को कदम #1और #2परमाणु रूप से करने से बचती हैं ।


-1

दोनों एक ही अवधारणा के हैं लेकिन परमाणु बूलियन में यह ऑपरेशन को परमाणुता प्रदान करेगा, जब बीच में सीपीयू स्विच होता है।

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