2014-04-20 4 views
5

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

[अद्यतन]
उदाहरण प्रिंट हमेशा 1 2 3 4 5 6 7 8 9 अस्थिर बिना।

package main; 

public class Counter 
{ 
    public static long count = 0; 
} 

public class UseCounter implements Runnable 
{ 
    public void increment() 
    { 
     synchronized (this) 
     {  
      Counter.count++; 
      System.out.print(Counter.count + " "); 
     } 
    } 

    @Override 
    public void run() 
    { 
     increment(); 
     increment(); 
     increment(); 
    } 
} 

public class DataRace 
{ 
    public static void main(String args[]) 
    { 
     UseCounter c = new UseCounter(); 

     Thread t1 = new Thread(c); 
     Thread t2 = new Thread(c); 
     Thread t3 = new Thread(c); 

     t1.start(); 
     t2.start(); 
     t3.start(); 
    } 
} 
+0

आपके अपडेट के बारे में: वर्तमान में यह वास्तव में प्रिंट करता है कुछ भी मतलब है। जब आप कम से कम उम्मीद करते हैं तो डेटा रेस की स्थिति आमतौर पर चुप रहती है और उन्हें पुन: पेश करने और हल करने में बहुत मुश्किल होती है। क्या मायने रखता है यदि आपने जावा मेमोरी मॉडल के नियमों का पालन किया है। –

+0

ठीक है धन्यवाद। हालांकि मैं बिना अस्थिर के गलत व्यवहार को पुन: उत्पन्न नहीं कर सकता (भले ही मैं लूप में कोड 1.000.000 बार चलाता हूं), मैं इसे ध्यान में रखूंगा। – Bevor

उत्तर

2

नहीं है, एक अस्थिर पहुँच अनुसार जावा मेमोरी मॉडल (हालांकि विशेष कार्यान्वयन पर, यह हो सकता है, लेकिन आप उस पर निर्भर नहीं करना चाहिए)

Java Language Specification 17.4.4 (on the Java Memory Model):

सिंक्रनाइज़ पहुँच से गर्भित नहीं है तुल्यकालन कार्यों सिंक्रनाइज़-साथ कार्यों, के रूप में परिभाषित पर संबंध इस प्रकार प्रेरित:

  • मॉनिटर मीटर सिंक्रनाइज़ पर एक अनलॉक कार्रवाई - बाद के सभी लॉक एम पर क्रियाएं (जहां "बाद में" सिंक्रनाइज़ेशन ऑर्डर के अनुसार परिभाषित किया गया है)।

  • एक अस्थिर चर वी (§8.3.1.4) सिंक्रनाइज़ करता है-के साथ सभी बाद के लिए एक लिखने किसी भी धागा (जहां "बाद में" तुल्यकालन क्रम के अनुसार परिभाषित किया गया है) द्वारा वी पढ़ता है।

volatile एक चर पर चल रही है और synchronized एक वस्तु का मॉनिटर ('लॉक') पर चल रही है।

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

+0

ठीक है, क्या इसका मतलब यह है कि कई थ्रेडों द्वारा बाह्य चरों तक पहुंचने पर मुझे हमेशा अस्थिरता का उपयोग करना चाहिए? मेरे अद्यतन प्रश्न देखें। यह हमेशा अस्थिर के बिना 1 2 3 4 5 6 7 8 9 प्रिंट करता है। तो इसका मतलब है कि ऐसा करने की गारंटी नहीं है? – Bevor

+0

जब एक थ्रेड बी एक अन्य थ्रेड ए के बाद एक अस्थिर फ़ील्ड को पढ़ता है (या लिखता है), तो थ्रेड बी * सभी * संशोधनों को देखेगा जो थ्रेड ए को किसी भी चर (किसी भी अस्थिर क्षेत्र तक पहुंचने से पहले), गैर-अस्थिर सहित लोगों को। एक ही अस्थिर चर का उपयोग करने से धागे के बीच संबंध "होता है" संबंध बनाता है। –

1

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

+0

धन्यवाद, लेकिन मुझे समझ में नहीं आता कि क्यों एक विवादित पहुंच है, क्योंकि जब मैं सिंक्रनाइज़ किए गए किसी ऑब्जेक्ट को लॉक और रिलीज़ करता हूं, तो क्या मुझे ध्यान रखना होगा कि पहले थ्रेड ने इसकी स्थानीय प्रतिलिपि बनाई है या नहीं? जब ऑब्जेक्ट अनलॉक हो रहा है, तो क्या यह गारंटी नहीं दी जाती है कि अगला थ्रेड संशोधित ऑब्जेक्ट तक पहुंच प्राप्त कर लेता है? – Bevor

+0

'अस्थिर' के पीछे विचार यह है कि आपको हमेशा चर के सबसे अद्यतित संस्करण मिलेंगे। जब कोई थ्रेड कैश रखता है तो यह नए मान प्राप्त करने में समय बचाने के लिए ऐसा करेगा लेकिन अस्थिर चर को कैश नहीं किया जाएगा – Rogue

0

आपका कोड 1 2 3 4 5 6 7 8 9 प्रिंट करने की गारंटी है।कारण यह है कि अगर आप एक अनुक्रम थ्रेड t1 Counter.count को लिखते हैं इस तरह के

  1. के रूप में है
  2. थ्रेड t1 बातें बताता वस्तु ग
  3. थ्रेड t2 ताले आपत्ति ग
  4. थ्रेड t2 पढ़ता Counter.count

तो यह गारंटी है कि चरण 4 में पढ़ने कदम पर लिखने देखता है 1.

यहके रूप में ही नहीं हैक्योंकि यह गारंटी नहीं है कि लेखन तुरंत स्मृति पर प्रतिबिंबित होता है, बल्कि यह केवल गारंटी है कि चरण 1 में लिखना चरण 3 के अंत में टी 2 के लिए दृश्यमान है।

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