क्या "सिंक्रनाइज़" या "अस्थिर" कीवर्ड के बिना यह कहना सही है कि एक थ्रेड द्वारा किए गए परिवर्तन दूसरे (या अनिर्धारित) द्वारा कभी नहीं देखे जाएंगे? मैं निम्नलिखित प्रोग्राम को मल्टी-कोर प्लेटफॉर्म में कई बार चलाता हूं और परिणाम अलग होते हैं। कभी-कभी कार्यक्रम कभी समाप्त नहीं होता है, जो अपेक्षित परिदृश्य है। लेकिन कभी-कभी यह "1" प्रिंट करके निकल जाता है।
JDK: jdk1.8.0_73
ओएस: सेंटोस लिनक्स रिलीज 7.1.1503

public class VolatileTest implements Runnable {
    private int i = 0;

    public void run() {
        i++;
        i++;
    }

    public int get() {
        return i;
    }

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        VolatileTest volatileTest = new VolatileTest();
        executorService.execute(volatileTest);
        while (true) {
            int i = volatileTest.get();
            if (i % 2 != 0) { // 
                System.out.format("i: %s \n", i);
                System.exit(0);
            }
        }
    }
}
0
Hel 14 जिंदा 2018, 10:50

4 जवाब

सबसे बढ़िया उत्तर

क्या "सिंक्रनाइज़" या "अस्थिर" कीवर्ड के बिना यह कहना सही है कि एक थ्रेड द्वारा किए गए परिवर्तन दूसरे (या गैर-नियतात्मक) द्वारा कभी नहीं देखे जाएंगे?

सही कथन यह है कि यह अनिर्दिष्ट है कि क्या होता है यदि कोई पहले होता है लेखन घटना से बाद के पढ़ने की घटना में संबंध नहीं है।

परिवर्तन तत्काल, या विलंबित हो सकते हैं, या वे कभी भी दिखाई नहीं दे सकते हैं।

और क्या अधिक है, परिवर्तन एक अप्रत्याशित क्रम में दिखाई दे सकते हैं।

आपके उदाहरण में, i चर के 3 संभावित मान हो सकते हैं, और यह अनिर्दिष्ट और अप्रत्याशित है जिसे main थ्रेड देखेगा। आप जो व्यवहार देखते हैं वह अप्रत्याशित नहीं है।

4
Stephen C 14 जिंदा 2018, 11:05

volatileTest.get() का आउटपुट 0, 1, or 2 हो सकता है क्योंकि सिंक्रोनाइज़ेशन नहीं है और रन विधि परमाणु नहीं है। इसके अलावा, प्रत्येक i++ ऑपरेशन परमाणु नहीं हैं।

इस प्रकार दोनों परिदृश्य लागू होते हैं:

  1. प्रिंटिंग 1 के साथ बाहर निकलना: एक बार i++ का ऑपरेशन पूरा हो गया और गेट का रिसल्फ़ एक था।
  2. दोनों i++ निर्देश पूरे हुए और get() ने 2 लौटाया और इस तरह अनंत लूप में फंस गए।
1
yamenk 14 जिंदा 2018, 11:05

क्या "सिंक्रनाइज़" या "अस्थिर" कीवर्ड के बिना यह कहना सही है कि एक थ्रेड द्वारा किए गए परिवर्तन दूसरे (या गैर-नियतात्मक) द्वारा कभी नहीं देखे जाएंगे?

यह सही नहीं है, इस प्रश्न का उत्तर पहले ही दिया जा चुका है (यह ए>)

रन विधि यह परमाणु/थ्रेड-सुरक्षित/सिंक्रनाइज़ नहीं है, इसलिए यह समझना काफी आसान है कि असाइनमेंट int i = volatileTest.get(); 0 से 2 तक मान प्राप्त कर सकता है। आप जो चाहते हैं उसे प्राप्त करने के लिए आपको एक lock प्राप्त करना चाहिए और डबल इंक्रीमेंट के बाद इसे फिर से जारी करें या मेथड सिग्नेचर में कीवर्ड synchronized डालें।

0
simo-r 14 जिंदा 2018, 11:01

"सिंक्रनाइज़" या "अस्थिर" कीवर्ड के बिना, एक थ्रेड द्वारा किए गए परिवर्तन दूसरे द्वारा कभी नहीं देखे जाएंगे

यह सही नहीं है। दृश्यता परिभाषित नहीं है क्योंकि यह जेआरई थ्रेड कैशिंग कार्यान्वयन पर निर्भर करता है।

executorService.execute (अस्थिर परीक्षण);

मेरा मानना ​​​​है कि जिस तरह से आप दृश्यता का परीक्षण करते हैं वह सबसे अच्छा नहीं है। बस स्टैक ओवरफ्लो खोजें और कई उदाहरण हैं (कुछ और भी बदतर)

कोड एक बार (और केवल एक बार) रन () विधि को निष्पादित करता है और थ्रेड कैश और थ्रेड शेड्यूलर के आधार पर आपको एक छोटा सा परिवर्तन i==1 मिलेगा

0
gusto2 14 जिंदा 2018, 11:01