Search code examples
javaconcurrencymemory-model

Does making a field `volatile` prevent all memory visibility issues in a concurrent situation?


Does making a class field volatile prevent all memory visibility issues with it in a concurrent situation ? Is it possible that for below class , a thread that gets a reference of a Test object sees x as 0 first ( the default value of int ) and then 10 ? I am thinking this to be possible if and only if the Constructor of Test gives away this reference without completing ( improper publishing ) . Can someone validate/correct me ?

class Test {
    volatile int x = 10;            
}

Second question: what if it was final int x=10; ?


Solution

  • You are actually not guaranteed to see x = 10 according to the JMM.

    For example if you have

    Test test =  null;
    
    Thread 1 -> test = new Test();
    Thread 2 -> test.x  == // even though test != null, x can be seen as 0 if the
                           // write of x hasn't yet occur
    

    Now if you had

    class Test{
      int y = 3;
      volatile x = 10;
    }
    

    If thread-2 reads x == 10 thread-2 is guaranteed to read y == 3

    To answer your second question.

    Having a final field will issue a storestore after the constructor and before publishing so having the field final will actually ensure you see x = 10.

    Edit: As yshavit noted. You lose the happens-before relationship I mention in my first example with final fields, that is as yshavit put it if thread-2 reads x == 10 it may not read y == 3 where x is a final field.