Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Volatile for reference type - Does it always avoid publication of references issues due to JMM?

Assuming this class:

public class AmIThreadSafe {

    private int a;
    private int b;

    AmIThreadSafe(int a, int b) {
        this.a = a;
        this.b = b;
    }
}

Assuming that instance's reference to this class (declared as volatile) is accessible by some threads (leading to race condition) as soon as the this(reference) escapes:

volatile AmIThreadSafe instance = new AmIThreadSafe(1,2);

Here, I'm sure that the fact of assigning instance reference happens-before reading by threads.

But what about the AmIThreadSafe's fields?

Does the external volatile keyword also imply an happens-before relation concerning a and b fields? Or is it rather possible to end up with any thread seeing stale values (default values 0 in this case since int) due to a potential statements reordering during constructor?

In other word, should I declare a and b final or volatile to prevent any surprises with the JMM or is just indicating volatile on the instance's reference enough?

----------------UPDATED POST - A GOOD ANSWER:----------------------------

The following article confirms by its sample that in my case, a and b are protected from JMM optimisations that prevent a permanent happens-before relation.

http://jeremymanson.blogspot.fr/2008/11/what-volatile-means-in-java.html

like image 724
Mik378 Avatar asked Nov 14 '12 00:11

Mik378


1 Answers

Declaring instance as volatile does not make its fields volatile, but if I understand your question correctly, then — yes, it's enough in your case.

Per §17.4.5 of the spec:

  • a volatile write in one thread happens-before any subsequent volatile read in another thread.
  • statements within the same thread have the happens-before relationship that you'd expect.
  • happens-before relationships are transitive.

So, if a thread perceives instance as having been initialized, then the initialization of instance happened-before it, and the initialization of instance's fields happened-before that, so the thread will perceive instance's fields as having been initialized.

like image 175
ruakh Avatar answered Oct 08 '22 12:10

ruakh