प्रोग्रामिंग में "परमाणु" का क्या अर्थ है?


274

प्रभावी जावा पुस्तक में, यह कहा गया है:

भाषा विनिर्देश इस बात की गारंटी देता है कि एक चर को पढ़ना या लिखना तब तक परमाणु है जब तक कि चर प्रकार longया double[जेएलएस, १.7.४. reading] नहीं है।

जावा प्रोग्रामिंग, या सामान्य रूप से प्रोग्रामिंग के संदर्भ में "परमाणु" का क्या अर्थ है?


24
एक समय में एक ऑपरेशन।
सुभ्रज्योति मजुमदार

1
एक बार में केवल एक ही ऑपरेशन को वेरिएबल पर किया जा सकता है।
17


1
मुझे संदेह है कि दर्शन के प्रश्न codereview.stackexchange.com में हैं
Phlip

यह देखते हुए कि कुछ चर डिफ़ॉल्ट रूप से परमाणु नहीं पढ़ते हैं और लिखते हैं, उन्हें घोषित करते हैं volatile longया volatile doubleपढ़ते हैं और परमाणु लिखते हैं।
H2ONaCl

जवाबों:


372

यहां एक उदाहरण दिया गया है, क्योंकि एक उदाहरण अक्सर एक लंबी व्याख्या की तुलना में स्पष्ट होता है। मान लीजिए fooकि एक प्रकार का चर है long। निम्नलिखित ऑपरेशन परमाणु ऑपरेशन नहीं है:

foo = 65465498L;

दरअसल, चर को दो अलग-अलग ऑपरेशनों का उपयोग करके लिखा गया है: एक जो पहले 32 बिट्स को लिखता है, और दूसरा वह जो पिछले 32 बिट्स को लिखता है। इसका मतलब है कि एक और सूत्र के मूल्य को पढ़ सकते हैं foo, और मध्यवर्ती स्थिति देख सकते हैं।

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

ऐसा करने का एक सरल तरीका यह है कि परिवर्तनशील को अस्थिर बनाया जाए :

private volatile long foo;

या चर तक हर पहुंच को सिंक्रनाइज़ करने के लिए:

public synchronized void setFoo(long value) {
    this.foo = value;
}

public synchronized long getFoo() {
    return this.foo;
}
// no other use of foo outside of these two methods, unless also synchronized

या इसे एक के साथ बदलने के लिए AtomicLong:

private AtomicLong foo;

75
तो यह मानकर चल रहा है कि यह 32-बिट सिस्टम में चल रहा है। क्या होगा अगर यह 64 बिट सिस्टम था? विल फू = 65465498L; परमाणु हो तो?
हरके

46
@ हर्क यदि आप 64 बिट जावा चला रहे हैं, तो हाँ।
जेरोइन

4
क्या यह C # और .NET पर भी लागू होता है? यदि हाँ, तो फू को परमाणु व्यवहार करने वाले के लिए, CLR 64-बिट होना चाहिए?
फाबियानो

5
@ फैबियानो यह लागू होता है और यहां इसे .NET में प्राप्त करने का तरीका बताया गया है क्योंकि हमारे पास जावा जैसे सिंक्रनाइज़ कीवर्ड नहीं हैं। stackoverflow.com/questions/541194/…
मफिन मैन

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

60

"परमाणु संचालन" का अर्थ है एक ऐसा ऑपरेशन जो अन्य सभी धागों के परिप्रेक्ष्य से तात्कालिक प्रतीत होता है। गारंटी लागू होने पर आपको आंशिक रूप से पूर्ण संचालन के बारे में चिंता करने की आवश्यकता नहीं है।


25

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

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

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

आपकी बोली इस बात पर प्रकाश डालती है कि सभी उदाहरणों में अपेक्षित व्यवहार नहीं होना चाहिए।


15

मेरे लिए बहुत उपयोगी होने के लिए बस एक पोस्ट परमाणु बनाम गैर-परमाणु संचालन मिला ।

"साझा मेमोरी पर अभिनय करने वाला एक ऑपरेशन परमाणु है यदि यह अन्य थ्रेड्स के सापेक्ष एकल चरण में पूरा होता है।

जब एक परमाणु स्टोर एक साझा मेमोरी पर किया जाता है, तो कोई भी अन्य धागा संशोधन को आधा-पूरा नहीं कर सकता है।

जब एक साझा चर पर एक परमाणु भार किया जाता है, तो यह पूरे मूल्य को पढ़ता है क्योंकि यह एक ही समय में दिखाई दिया था। "


14

यदि आपके पास नीचे दिए गए कोड में m1 और m2 के तरीकों को निष्पादित करने वाले कई सूत्र हैं:

class SomeClass {
    private int i = 0;

    public void m1() { i = 5; }
    public int m2() { return i; }
}

आपके पास गारंटी है कि किसी भी थ्रेड कॉलिंग m2को या तो 0 या 5 पढ़ा जाएगा।

दूसरी ओर, इस कोड के साथ (जहां iएक लंबा समय है):

class SomeClass {
    private long i = 0;

    public void m1() { i = 1234567890L; }
    public long m2() { return i; }
}

एक थ्रेड कॉलिंग m20, 1234567890L, या कुछ अन्य यादृच्छिक मान पढ़ सकता है क्योंकि कथन के i = 1234567890Lलिए परमाणु होने की गारंटी नहीं है long(एक JVM पहले 32 बिट्स और अंतिम 32 बिट्स को दो ऑपरेशन में लिख सकता है और एक धागा iबीच में देख सकता है। ।


आपको क्यों लगता है कि "लंबे" समस्या का कारण बनता है जबकि "इंट" नहीं करता है? कृपया यहाँ देख geekswithblogs.net/BlackRabbitCoder/archive/2012/08/09/...
onmyway133

1
जावा में परमाणु होने के लिए @entropy लंबी और दोहरी असाइनमेंट की गारंटी नहीं है। तो आप एक लंबे समय को पढ़ सकते हैं जहां केवल आधे बिट्स को एक असाइनमेंट के बाद अपडेट किया गया है।
अस्वच्छ

0

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

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