2013-02-25 18 views
6

मैं केवल थ्रेडिंग परिप्रेक्ष्य में पूछ रहा हूं ... शायद कई बार जवाब दिया गया है लेकिन कृपया इसे समझने में मेरी सहायता करें।स्टेटिक वैरिएबल बनाम अस्थिर

संदर्भ के साथ यहाँ Volatile Vs Static in java

पोस्ट करने के लिए एक स्थिर चर मूल्य भी सभी धागे के लिए एक मूल्य होने जा रहा है पूछ, तो क्यों हम अस्थिर के लिए जाना चाहिए? मैं निम्नलिखित उदाहरण पाया:

public class VolatileExample { 
public static void main(String args[]) { 
    new ExampleThread("Thread 1 ").start(); 
    new ExampleThread("Thread 2 ").start(); 
} 

} 
class ExampleThread extends Thread { 
private static volatile int testValue = 1; 
public ExampleThread(String str){ 
    super(str); 
} 
public void run() { 
    for (int i = 0; i < 3; i++) { 
     try { 
      System.out.println(getName() + " : "+i); 
      if (getName().compareTo("Thread 1 ") == 0) 
      { 
       testValue++; 
       System.out.println("Test Value T1: " + testValue); 
      } 
      if (getName().compareTo("Thread 2 ") == 0) 
      { 
       System.out.println("Test Value T2: " + testValue); 
      }     
      Thread.sleep(1000); 
     } catch (InterruptedException exception) { 
      exception.printStackTrace(); 
      } 
     } 
     } 
     } 

आउटपुट:

Thread 1 : 0 
Test Value T1: 2 
Thread 2 : 0 
Test Value T2: 2 
Thread 1 : 1 
Test Value T1: 3 
Thread 2 : 1 
Test Value T2: 3 
Thread 1 : 2 
Test Value T1: 4 
Thread 2 : 2 
Test Value T2: 4 

अगर मैं testValue से स्थिर निकालने के लिए, प्राप्त परिणाम:

Thread 1 : 0 
Test Value T1: 2 
Thread 2 : 0 
Test Value T2: 1 
Thread 1 : 1 
Test Value T1: 3 
Thread 2 : 1 
Test Value T2: 1 
Thread 1 : 2 
Test Value T1: 4 
Thread 2 : 2 
Test Value T2: 1 

क्यों धागा 2 अद्यतन मूल्य नहीं पढ़ रहा है? अगर इसे स्थैतिक बनाया जाना है, अस्थिरता का उपयोग क्या है?

क्या कोई अस्थिरता के एक अच्छे उदाहरण को लिंक दे सकता है जहां वह चर स्थिर नहीं घोषित किया जाता है।

धन्यवाद

+1

स्वीकार किए जाते हैं आपके प्रश्न के उत्तर से जुड़े पोस्ट पर उत्तर दें। –

+2

बाकी उत्तर पढ़ें - esp। ** स्थिर अस्थिर ** के बारे में थोड़ा ** .. – Nim

+0

'स्थिर '=/=' अंतिम'। –

उत्तर

4

समस्या यह है कि ++ परमाणु नहीं है। कोड को इसके बजाय AtomicInteger का उपयोग करना चाहिए। static चर के साथ, दोनों थ्रेड एक ही मान को अपडेट करने का प्रयास कर रहे हैं और ++ वास्तव में 3 ऑपरेशंस है: प्राप्त करें, +1 करें और स्टोर करें। इसका मतलब है कि दोनों धागे के बीच दौड़ की स्थिति है और वे एक-दूसरे को ओवरराइट कर रहे हैं।

क्यों थ्रेड 2 अद्यतन मूल्य नहीं पढ़ रहा है? अगर इसे स्थैतिक बनाया जाना है, अस्थिरता का उपयोग क्या है?

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

आपको AtomicInteger का उपयोग करना चाहिए।यह एक volatile int लपेटता लेकिन यह भी वेतन वृद्धि के संचालन के विशेष हैंडलिंग प्रदान करता है:

private static AtomicInteger testValue = new AtomicInteger(1); 
... 
testValue.incrementAndGet(); 

किसी अस्थिर का एक अच्छा उदाहरण है, जहां कि चर स्थिर घोषित नहीं किया गया है के लिए लिंक दे सकते हैं।

आपको एक गैर-स्थैतिक क्षेत्र पर volatile की आवश्यकता होगी जब इसे एकाधिक धागे द्वारा साझा किया गया था। उदाहरण के लिए, यदि आपने testValue को VolatileExample वर्ग में स्थानांतरित किया है और फिर VolatileExample कक्षा के दोनों ही धागे में उसी उदाहरण को पारित किया है, तो वे testValue तक पहुंच सकते हैं।

+0

आपके लिए मूल्यवान अंतर्दृष्टि धन्यवाद, मैं इसका परीक्षण करूंगा, चर कहीं। – Dhananjay

+0

बस दोहराने के लिए, आप 'अस्थिर' पर '++' नहीं कर सकते हैं, भले ही यह स्थैतिक है या नहीं @ दंजंजय। – Gray

+0

मैंने रननेबल क्लास के बाहर चर डालने की कोशिश की।
' सार्वजनिक वर्ग खाता { सार्वजनिक डबल बैलेंस = 0; सार्वजनिक स्थैतिक शून्य मुख्य (स्ट्रिंग ... एस) { खाता aAccount = नया खाता(); जमा करें एक डीपॉजिट थ्रेड 1 = नया जमा थ्रेड (खाता); थ्रेड थ्रेड 1 = नया थ्रेड (aDepositThread1, "thread1"); जमा थ्रेड 1 aDepositThread2 = नया जमा थ्रेड 1 (खाता); थ्रेड thread2 = नया थ्रेड (aDepositThread2, "thread2"); thread1.start(); thread2.start(); } } ' लेकिन यदि हम एक ही वस्तु को दो धागे में पारित कर रहे हैं, तो इसे अद्यतन मूल्य प्राप्त होगा? – Dhananjay

4

volatile के उपयोग के लिए सुनिश्चित करें कि सभी थ्रेड एक ही समय में एक ही मूल्य देखते हैं। अनिवार्य रूप से यह कह रहा है कि इस चर को कभी कैश नहीं किया जाना चाहिए।

कोड में प्रदर्शित करना मुश्किल है क्योंकि कैशिंग रणनीतियां सीपीयू से सीपीयू और जेआरई से जेआरई तक बदलती हैं।

क्या volatile JRE के लिए कह रहा है आप कभी भी इस मूल्य को कैश करने के क्योंकि आपको लगता है कि आप ऐसा करने ... न द्वारा एक छोटे से तेजी से चलाने के कोड बना सकता है परीक्षा रहे हैं, तो है! ... मैं आपके से प्रोग्रामिंग के बारे में बहुत कुछ जानता हूं और मुझे संदेह की छाया के बिना पता है कि यदि आप करते हैं तो आप मेरा कोड तोड़ देंगे।

0

इस मामले में, जब tou static संशोधक आपको चर बदल गया है, क्योंकि अब, प्रत्येक ExampleThread, अपने स्वयं के testValue है कि के लिए हटा दिया, भंडारण मूल्य प्रत्येक थ्रेड उदाहरण के लिए अलग है।

static संशोधक का अर्थ:

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

संदर्भ: Understanding Instance and Class Members

बारे volatile, आप वर्ग VolatileExample करने के लिए testValue चर चलती है, इस तरह के परीक्षण की एक अलग तरह की कोशिश करते हैं,:

public class VolatileExample { 
    private volatile int testValue = 1; 
... 
} 

फिर, ExampleThread से testVariable हटाने और कोड चलाते हैं। इसका उत्पादन पहले की तरह होना चाहिए।

volatile संशोधक का अर्थ: क्योंकि एक अस्थिर चर के लिए किसी भी लिखने स्थापित करता है एक होता है-पहले बाद के साथ संबंध है कि एक ही चर के पढ़ता

अस्थिर चर का उपयोग करना, स्मृति स्थिरता त्रुटियों के जोखिम को कम करता है। इसका मतलब है कि एक अस्थिर चर में परिवर्तन हमेशा अन्य थ्रेड

लिए दिखाई दे रहे हैं

संदर्भ: Atomic Access

0

आपका आखिरी सवाल "किसी अस्थिर का एक अच्छा उदाहरण है, जहां कि चर स्थिर घोषित नहीं किया गया है के लिए लिंक दे सकते हैं। " इस अवधारणा को स्पष्ट रूप से समझने के लिए बनाया गया और मैं एक उदाहरण के साथ आया था।

public class VolatileExample { 

    // public static volatile int testValue = 1; 
    public int nonstatic=8; 
    public static void main(String args[]) { 
     VolatileExample volatileExample=new VolatileExample(); 
     new ExampleThread("Thread 1 ",volatileExample).start(); 
     new ExampleThread("Thread 2 ",volatileExample).start(); 
    } 

} 
class ExampleThread extends Thread { 
VolatileExample volatileExample; 
    public ExampleThread(String str,VolatileExample volatileExample){ 
     super(str); 
     this.volatileExample=volatileExample; 
    } 
    public void run() { 
     for (int i = 0; i < 3; i++) { 
      try { 
       if (getName().compareTo("Thread 1 ") == 0) 
       { 
        volatileExample.nonstatic++; 
        System.out.println("Test Value T1: " + volatileExample.nonstatic); 


       } 
       if (getName().compareTo("Thread 2 ") == 0) 
       { 
        System.out.println("Test Value T2: " + volatileExample.nonstatic); 
        Thread.sleep(1); 
       } 
       // Thread.sleep(1000); 
      } catch (InterruptedException exception) { 
       exception.printStackTrace(); 
      } 
     } 
    } 
} 

अब सार्वजनिक int nonstatic = 8 बनाकर परिवर्तन देखें। अस्थिर

जब यह अस्थिर किया जाता है उत्पादन, होगा

टेस्ट मूल्य टी 1 के बाद: 9 टेस्ट मूल्य टी 1: 10 टेस्ट मूल्य टी 1: 11 टेस्ट मूल्य टी 2: 11 टेस्ट मूल्य टी 2: 11 टेस्ट मूल्य टी 2: 11

प्रक्रिया के बाद परिणाम है बाहर निकलने के कोड 0

के साथ समाप्त करता है, तो यह गैर अस्थिर बना है: टेस्ट मूल्य टी 1: 9 टेस्ट मूल्य टी 2 : 9 टेस्ट मूल्य टी 1: 10 टेस्ट मूल्य टी 1: 11 टेस्ट मूल्य टी 2: 11 टेस्ट मूल्य टी 2: 11

प्रक्रिया से बाहर निकलने कोड के साथ समाप्त 0

अवलोकन: चूंकि वाष्पशील कीवर्ड सीधे करने के लिए धागा बनाता है इसे मुख्य मेमोरी में लिखें, थ्रेड लूप के लिए तेज़ी से वापस आ जाता है, इसलिए जब इसे अस्थिर बनाया जाता है, तो थ्रेड 1 ने अपना काम तेजी से पूरा कर लिया और थ्रेड 2 की बारी शुरू करने से पहले लूप पर वापस आ गया।

दूसरी ओर, इसे गैर-अस्थिर बनाते हुए, थ्रेड को अपने लोकल कैश को अपडेट करने के लिए बनाता है और फिर इसे मुख्य स्मृति में रिपोर्ट करता है ... इसलिए इस चक्र के दौरान, थ्रेड 2 दौड़ में प्रवेश करता था।

पीएलजी नोट, मेरे पास VolatileExample क्लास में "गैर स्थैतिक" चर है, उदाहरण के लिए इस प्रदर्शन को प्रदर्शित करने के लिए नहीं।

आपका अन्य प्रश्न है: क्यों थ्रेड 2 अद्यतन मूल्य नहीं पढ़ रहा है? अगर इसे स्थैतिक बनाया जाना है, अस्थिरता का उपयोग क्या है?

ठीक है, यदि u यह testvalue गैर स्थिर है, तो इसके लिए कुछ भी नहीं लेकिन दो अलग अलग वस्तुओं Thread1 और वर्ग के Thread2 अपने स्वयं के varibles testvalue पर काम कर ExampleThread .... इतना अस्थिर नहीं करता है वास्तव में कोई फर्क .. बनाने

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