Interest in multithreading with volatile int

Ok I wrote code and got an unexpected result, and I don't know how to explain this result. Can someone help me with this?

public class JMM {
static volatile Boolean ready = false;
static volatile int data = 0;

public static void main() {
    Log.d("JMM", "start");
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            data = 1;
            ready = true;
        }
    }).start();

    for(int i = 0; i < 100; i++) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (!ready)
                    Log.d("JMM", "second thread data " + data);
            }
        }).start();
    }
}
}

I ran it on Nexus 5 (it has 4 cores):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MM.main();
}

result:

D / JMM: data of the second stream 0

...

D / JMM: data of the second stream 0

D / JMM: data of the second stream 0

D / JMM: data of the second stream 0

D / JMM: data of the second stream 0

D / JMM: data of the second stream 0

D / JMM: data of the second stream 1

D / JMM: data of the second stream 1

D / JMM: data of the second stream 1

D / JMM: data of the second stream 0

D / JMM: data of the second stream 0

D / JMM: data of the second stream 1

D / JMM: data of the second stream 1

D / JMM: data of the second stream 1

D / JMM: data of the second stream 1

What am I expecting? This int is the default atomic type (however, I wrote volatile before), and it did not cache its value. But I see that different threads are reading different values ​​from the same field at the same moment. Who can explain this to me?

+4
source share
1 answer

Consider what happens on this line:

Log.d("JMM", "second thread data " + data);
  • Read data
  • String " "
  • Log.d

, , , 1 , 4. :

Thread 1               | Thread 2
-----------------------+-----------------------
1. read "data"         |
2. concat string:      |
  "...data 0"          |
     <<< third thread updates data = 1 >>>
                       | 1. read "data"
                       | 2. concat string:
                       |   "... data 1"
                       | 3. invoke Log.d(...)
                       | 4. print message
                       |   with "... data 1"
3. invoke Log.d(...)   | 
4. print message       |
  with "data 0"        |
+2

All Articles