2011-10-18 18 views
43

जावा थ्रेड-सुरक्षित में अस्थिर int है? यही है, क्या इसे सुरक्षित रूप से पढ़ा जा सकता है और लॉक किए बिना लिखा जा सकता है?जावा थ्रेड-सुरक्षित में अस्थिर int है?

+0

यदि आप अक्सर डेटा बदल रहे हैं तो यह सुरक्षित नहीं है –

उत्तर

57

हां, आप इसे पढ़ सकते हैं और इसे सुरक्षित रूप से लिख सकते हैं - लेकिन आप कुछ भी ऐसा नहीं कर सकते हैं जैसे इसे सुरक्षित रूप से बढ़ाना, क्योंकि यह एक पढ़ा/संशोधित/लिखना चक्र है। यह भी बात है कि यह अन्य चरों तक पहुंच के साथ कैसे इंटरैक्ट करता है। (memory model section of the JLS for more details देखें)

अस्थिर की सटीक प्रकृति स्पष्ट रूप से भ्रामक है - मैं व्यक्तिगत रूप से आम तौर पर AtomicInteger बजाय प्रयोग करेंगे, यकीन है कि मैं इसे सही करने का एक आसान तरीका है।

+13

आप 'अस्थिर int' को सुरक्षित रूप से बढ़ा सकते हैं, लेकिन आपको '++' को पूरे लोड 'AtomicIntegerFieldUpdater' से प्रतिस्थापित करने की आवश्यकता होगी। (जितना तेज़ नहीं है, लेकिन यदि एक्सेस को सरल पढ़ने/लिखने और/या मेमोरी ओवरहेड का प्रभुत्व है, तो यह उपयोगी हो सकता है) –

+0

@ टॉमहॉविन-टाइललाइन: विवरण के लिए धन्यवाद :) –

+2

++ समस्या के पूर्ण चित्रण के लिए , मैंने पाया http://jeremymanson.blogspot.com/2007/08/volatile-does-not-mean-atomic.html अच्छा और स्पष्ट। –

5

[...] सुरक्षित रूप से पढ़ सकते हैं और ताला लगा के बिना करने के लिए लिखा जा करने में सक्षम होने के रूप में?

हाँ, पढ़ने हमेशा पिछले लिखने, (और दोनों रीड और राईट परमाणु संचालन कर रहे हैं) के मूल्य में परिणाम देगा।

एक अस्थिर पढ़ने/लिखने निष्पादन में पहले से जुड़े होने वाले पहले-परिचय होता है।

जावा भाषा विशिष्टता Chapter 17: Threads and Locks

एक अस्थिर क्षेत्र (§8.3.1.4) होता है-पहले कि क्षेत्र के हर बाद पढ़ने के लिए एक लिखने से।

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

जैसा कि जॉन स्कीट बताता है, अस्थिर चर का उपयोग सीमित है, और आपको सामान्य रूप से java.util.concurrent पैकेज से कक्षाओं का उपयोग करने पर विचार करना चाहिए।

+0

"जब वे अस्थिर चर के साथ काम करते हैं (...) _latest value variable_ पर लिखा गया है" और ** ** ** अस्थिर 'चर के साथ, "चर के लिए लिखा गया नवीनतम मान" जैसी कोई चीज़ नहीं है। समझने के लिए आपको "चर के लिए लिखे नवीनतम मूल्य" वाक्यांश के लिए 'अस्थिर' की आवश्यकता है। – curiousguy

+0

मैं असहमत हूं। अगर मैं 'x = 1 करता हूं; x = 2; 'एक थ्रेड में, और उसके बाद 'System.out.println (x)' किसी अन्य में (* लंबे समय के बाद *' x = 2' निष्पादित किया गया है, यह अभी भी '1' प्रिंट कर सकता है। मेरा मतलब यह है कि यदि '2'' x' पर लिखा गया मान था, तो 'x' अभी भी किसी अन्य थ्रेड में' 2' का मूल्यांकन नहीं कर सकता है। – aioobe

+0

यदि 'x'' अस्थिर नहीं है ': "_after' x = 2' निष्पादित _ "/ पहले 'x = 2' निष्पादित किया गया है ** ** अच्छी तरह से परिभाषित नहीं किया गया है ** यदि आप वास्तव में 2 पर सेट होने के बाद' x' पढ़ते हैं, तो निश्चित रूप से आपको 2. – curiousguy

1

जावा में अस्थिर int तक पहुंच थ्रेड-सुरक्षित होगी। जब मैं एक्सेस कहता हूं तो मेरा मतलब यूनिट ऑपरेशन है, जैसे volatile_var = 10 या int temp = volatile_var (मूल रूप से निरंतर मानों के साथ लिखना/पढ़ना)। जावा में अस्थिर कीवर्ड दो चीजों को सुनिश्चित करता है:

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

हालांकि जॉन स्कीट का उल्लेख सही है कि गैर परमाणु संचालन (volatile_var = volatile + 1) में अलग-अलग धागे अप्रत्याशित परिणाम प्राप्त कर सकते हैं।

0

हमेशा नहीं।

यदि एकाधिक धागे लिख रहे हैं और चर पढ़ रहे हैं तो यह थ्रेड सुरक्षित नहीं है। यदि आपके पास एक लेखक धागा और एकाधिक पाठक धागे हैं तो यह थ्रेड सुरक्षित है।

आप सुरक्षित रूप से देख रहे हैं थ्रेड के लिए, AtomicXXX कक्षाएं

वर्गों है कि एकल चर पर ताला मुक्त धागा सुरक्षित प्रोग्रामिंग का समर्थन का एक छोटा सा टूलकिट का उपयोग करें।

boolean compareAndSet(expectedValue, updateValue); 

@ देखें:

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

Volatile boolean vs AtomicBoolean

+0

का क्या मतलब होगा "थ्रेड सुरक्षित"? – curiousguy

+0

https://stackoverflow.com/questions/2033879/what-does-threadsafe-mean –

0

तो एक अस्थिर किसी अन्य अस्थिर चर अपने धागा पढ़ने ऑपरेशन के लिए सुरक्षित पर निर्भर नहीं है। लिखने के अस्थिरता के मामले में थ्रेड सुरक्षा की गारंटी नहीं है।

मान लें कि आपके पास एक वैरिएबल है जो अस्थिर है और इसका मान किसी अन्य अस्थिर चर पर निर्भर है। अब थ्रेड -1 एक्सेस वैरिएबल जे और इसे बढ़ाएं और सीपीयू कैश से मुख्य मेमोरी में इसे अपडेट करने जा रहा है। यदि थ्रेड -2
वैरिएबल को पढ़ता है तो थ्रेड -1 वास्तव में मुख्य स्मृति में जे को अपडेट कर सकता है। मेरा मूल्य जे के पुराने मूल्य के अनुसार होगा जो गलत होगा। इसे गंदा पढ़ा भी कहा जाता है।

0

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

2) सिंक्रनाइज़ किए गए ब्लॉक के विकल्प के रूप में आप java.util.concurrent पैकेज में पाए गए कई परमाणु डेटा प्रकारों में से एक का भी उपयोग कर सकते हैं। उदाहरण के लिए, परमाणु लांग या परमाणु संदर्भ या दूसरों में से एक।

यदि आपके पास एक लेखक धागा और एकाधिक पाठक धागे हैं तो यह थ्रेड सुरक्षित है।

class Foo { 
private volatile Helper helper = null; 
public Helper getHelper() { 
if (helper == null) { 
synchronized(this) { 
if (helper == null) 
helper = new Helper(); 
} 
} 
return helper; 
} 
} 

नोट: यदि सहायक अपरिवर्तनीय है तो अस्थिर keyword.Here सिंगलटन की कोई जरूरत नहीं ठीक से काम करेंगे।

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

public class Counter{ 
private volatile int i; 
public int increment(){ 
i++; 
} 
} 

नोट: यहां अस्थिर मदद नहीं करेगा।

+0

जावा में, दौड़ की स्थिति और ** डेटा ** दौड़ को अलग करने के लिए सावधान रहें – curiousguy

संबंधित मुद्दे