Search code examples
javavolatilejava.util.concurrentjava-memory-model

Is it guaranteed that volatile field would be properly initialized


Here:

An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.

Are the same guarantees held for the volatile field? What if the y field in the following example would be volatile could we observe 0?

class FinalFieldExample { 
final int x;
int y; 
static FinalFieldExample f;

public FinalFieldExample() {
    x = 3; 
    y = 4; 
} 

static void writer() {
    f = new FinalFieldExample();
} 

static void reader() {
    if (f != null) {
        int i = f.x;  // guaranteed to see 3  
        int j = f.y;  // could see 0
    } 
} 

}


Solution

  • Yes, it is possible to see 0 when

    class FinalFieldExample { 
      final int x;
      volatile int y;
      static FinalFieldExample f;
      ...
    }
    

    The short explanation:

    • writer() thread publishes f = new FinalFieldExample() object via a data race
    • because of this data race, reader() thread is allowed see f = new FinalFieldExample() object as semi-initialized.
      In particular, reader() thread can see a value of y that was before y = 4; — i.e. initial value 0.

    More detailed explanations are here.

    You can reproduce this behavior on ARM64 with this jcstress test.