Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Java not see the updated value from another thread?

Please look at this code(taken from Effective Java book)

import java.util.concurrent.TimeUnit;


public class Main {
private static boolean stopReq;
public static void main(String[] args) throws InterruptedException {


    Thread bgw = new Thread(new Runnable()
    {
        public void run(){

        int i = 0;
        while(!stopReq){ i++;}
        }
        });
    bgw.start();
    TimeUnit.SECONDS.sleep(1);
    stopReq = true;

}

}

Why does the bgw thread get stuck in an infinite loop? Is it caching it's own copy of stopReq when it reached the loop? So it never sees the updated value from the other thread?

I understand the solution to this problem would be synchronizing or a volatile variable, but I am curious to why this current implementation doesn't work.

thanks

like image 707
William Avatar asked Jan 15 '14 11:01

William


2 Answers

Your explanation is right.

The compiler detects than stopReq is never modified in the loop and since it is not volatile, optimizes the while(!stopReq) instruction to while(true).

Even though the value changes later, the thread does not even read it any more.

like image 70
Jean Logeart Avatar answered Oct 06 '22 00:10

Jean Logeart


You should read more about Java Memory Model to better understand all the implications.

Shortly, the stopReq variable not being volatile or included in a synchronized block gives the VM freedom to use an optimized local storage (eg. registers etc) which is not guaranteed to propagate changes immediately across the threads.

When you declare the variable as volatile the VM will make sure that after each variable write a "memory write barrier" is inserted which will force all the local changes to be spilled to the real memory location thus making it visible to all the other threads (the same barrier is placed at the end of a synchronized block eg.)

like image 31
JB- Avatar answered Oct 05 '22 23:10

JB-