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
Declaring
instanceasvolatiledoes not make its fieldsvolatile, but if I understand your question correctly, then — yes, it’s enough in your case.Per §17.4.5 of the spec:
volatilewrite in one thread happens-before any subsequentvolatileread in another thread.So, if a thread perceives
instanceas having been initialized, then the initialization ofinstancehappened-before it, and the initialization ofinstance‘s fields happened-before that, so the thread will perceiveinstance‘s fields as having been initialized.