Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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; ?

like image 221
Bhaskar Avatar asked Jan 06 '12 21:01

Bhaskar


1 Answers

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.

like image 163
John Vint Avatar answered Sep 21 '22 20:09

John Vint