Search code examples
javalockingvolatilebarrier

Can volatile make common variables visible for different threads?


public class TestMemVisbility {
    static  volatile int flag;
    static int[] arr=new int[100000];
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(flag==0) ;
                for(int i=0;i<100000;i++)
                    if(arr[i]!=i) System.out.println("false");
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                flag=0;
                for(int i=0;i<100000;i++)
                    arr[i]=i;
                flag=1;
            }

        }).start();
    }
}

As I understand,the volatile can only make itself(not common varibles before it) visible for other threads.So I want test it,but there printing nothing.


Solution

  • The Java Memory model is defined as a set of happens before rules. With a happens before rule you get the guarantee that if 'a happens before b' than 'b will see the effects of a'.

    So imagine we would have the following code:

    int a;
    volatile int b;
    
    void foo(){
       a=1; //Action1
       b=1; //Action2
    }
    
    void bar(){
       int _b = b; //Action3
       int _a = a; //Action4
       ...
    }
    

    One thread calls foo and after it has completed, another thread calls bar. Will the second thread see the right value of a?

    Since Action1 occurs before Action2 due to program order, there is a happens before relation between Action1 and Action 2. This is called the program order rule.

    There is a happens before relation between Action 2 and Action 3 because Action2 occurred before Action 3. This is called the volatile variable rule.

    Since Action 3 occurs before Action 4 due to program order, there is a happens before relation between Action 3 and Action 4. This is the program order rule again.

    One other important rule of the Java Memory model is the transitivity rule, so if A happens before B and B happens before C, then A happens before C. We can apply this rule here twice and determine that there is a happens before relation between Action 1 and Action 4.

    So thread 2 will see the right value of a.

    A volatile can make 'non volatile' variables visible to another thread. A very practical example would be some POJO being being enqueued on a BlockingQueue by 1 thread and dequeued by another thread. This POJO can be a regular object without any volatile fields. The queue will provide the happens before relation based on the monitor lock rule or volatile variable rule. In the documentation this is often called memory consistency effects.

    Note. The volatile variable rule can only be applied on a volatile field of the same object instance.