2010-03-05 14 views
5

जावा में एक परमाणु संदर्भ वर्ग मौजूद है। क्या इसका मतलब यह है कि संदर्भ स्थापित करना एक परमाणु संचालन नहीं है?जावा में परमाणु संदर्भ - थ्रेड-सुरक्षित वातावरण में संदर्भ स्थापित करने के लिए आवश्यक है?

उदाहरण के लिए, इस सूत्र के लिए सुरक्षित नहीं है सी # में (यह सोचते हैं कि दिए गए मान को संशोधित नहीं किया जा सकता है) ?:

public void someMethod() 
{ 
    this.someList = Collections.unmodifiableList(new LinkedList<Object>()); 
} 

public List<Object> getReadOnlyList() 
{ 
    return someList; 
} 

कैसे के बारे में?

+3

आपका उदाहरण पूरी तरह से थ्रेड-सुरक्षित नहीं है। यदि सूची असुरक्षित रूप से प्रकाशित की गई है तो आप सामग्री को सही ढंग से नहीं पढ़ सकते हैं (हालांकि 'लिंक्डलिस्ट' के कार्यान्वयन से आप इसे खाली होने की अनुमति दे सकते हैं)। –

+0

@ टॉम: क्या आपका मतलब है कि अन्य धागे को कुछ लिस्ट फ़ील्ड के लिए पुराना, कैश किया गया मान मिल सकता है, या कुछ लिस्ट फ़ील्ड वास्तव में "अर्ध-लिखित" हो सकता है? – radai

+0

@ hatchetman82 मेरा मतलब है कि नए संदर्भ को पढ़ने के बाद, जिस ऑब्जेक्ट को इंगित करता है वह पूरी तरह से अपडेट नहीं हो सकता है। तो अगर मैं असुरक्षित रूप से सार्वजनिक 'नया java.awt.Point (1, 2) 'था, तो मैं ऑब्जेक्ट को किसी अन्य थ्रेड में पढ़ने में सक्षम हो सकता हूं लेकिन' x' और 'y' फ़ील्ड अभी भी शून्य हो सकते हैं। –

उत्तर

3

Java Language Specification, version 3.0, Section 17.7 के अनुसार:

लिए लिखता है और संदर्भ की पढ़ता हमेशा परमाणु होते हैं, वे 32 के रूप में या 64 बिट मूल्यों कार्यान्वित कर रहे हैं चाहे।

परमाणु संदर्भ एक तुलना करने और परमाणु क्रिया के रूप में सेट करने में सक्षम बनाता है।

public boolean changeList(List<Object> oldValue, List<Object> newValue) { 
    if (this.someList == oldValue) { 
     // someList could be changed by another thread after that compare, 
     // and before this set 
     this.someList = newValue; 
     return true; 
    } 
    return false; 
} 
+1

'सूची' पैरामीटर में कुछ जेनेरिक के साथ क्या कर सकता है। –

+0

सार्वजनिक बूलियन परिवर्तन सूची (सूची पुरानी वैल्यू, सूची newValue) का उपयोग करें – Lombo

1

आप उपयोग नहीं करते हैं AtomicReference या अस्थिर कीवर्ड और धागा संदर्भ पढ़ने एक है कि यह करने के लिए लिखा था नहीं है, वहाँ पढ़ने कि कोई गारंटी नहीं है:

यह threadsafe नहीं है धागा अद्यतन मूल्य देखेंगे।

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

3

कभी-कभी java.util.concurrent.atomic के लिए अनदेखा कुछ आम उपयोगों पर विस्तारित करता है।

परिशिष्ट: इसी प्रकार package descriptionjava.util.concurrent के लिए JLS §17 में विस्तृत कई आवश्यक बिंदुओं को सारांशित करता है। यदि आपका List अपरिवर्तनीय करने के लिए है और इसे करने के लिए एक संदर्भ final बनाया जा सकता है

इसके अलावा, Final Field Semantics के संभावित लाभ पर विचार करें।

1

जहां तक ​​सी #, मुझे यह जवाब मिला। एक संदर्भ सेट करना सी # भाषा विनिर्देश की धारा 5.5 के अनुसार एक परमाणु संचालन है।

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

+0

प्रश्न थ्रेड सुरक्षा के बारे में है, परमाणुता नहीं। उदाहरण के लिए, जावा में एक गैर सिंक्रनाइज़ संदर्भ चर पढ़ने पर परमाणु हो सकता है लेकिन ** ** ** थ्रेड-सुरक्षित नहीं हो सकता है। –

+0

सीएफ। http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.7 – trashgod

+0

बिंदु यह है कि परमाणुता गारंटी देता है कि आप या तो संदर्भ (या शून्य) या नए मान का पुराना मान पढ़ेंगे संदर्भ का लेकिन कभी भी एक और दूसरे का हिस्सा नहीं है। –

3

क्या इसका मतलब यह है कि संदर्भ स्थापित करना एक परमाणु संचालन नहीं है?

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

परमाणु का अर्थ है कि कोई पर्यवेक्षक (थ्रेड) या तो पुराने मान या चर के नए मान को देखता है, और कुछ और नहीं। इसका मतलब यह नहीं है कि जब वे चर को देखते हैं तो सभी पर्यवेक्षकों को नया मान दिखाई देता है। (और जैसा कि @Tom इंगित करता है, संदर्भ चर की परमाणुता वस्तु के परमाणु गुणों के बारे में कुछ भी नहीं कहती है।)

सभी पर्यवेक्षकों के लिए चर में नए मान को देखने के लिए, कुछ सिंक्रनाइज़ेशन होने की आवश्यकता है पर। एक चर के लिए एक अद्यतन के लिए, यह होगा यदि:

  • चर volatile के रूप में घोषित किया जाता है, या
  • पहुँच/चर के लिए अद्यतन एक ही आदिम मॉनिटर ताला द्वारा सिंक्रनाइज़ किए जाते हैं।

एक चर ही आप आम तौर पर इन वर्गों में से एक का उपयोग करें यदि आप ताले से बचना चाहते हैं और आप इस तरह के परमाणु के रूप में काम करने के लिए चाहते हैं कि, प्रासंगिक "AtomicXxx" वर्ग भी धागा सुरक्षित हो जाएगा में लपेटा जाता है "की तुलना और बदलें"।

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