Given a class A with variable x. Variable x is set in class constructor:
A() {
x = 77;
}
We want to publish x to some other thread. Consider th
My answer comes from the best page on the internet, in particular chapter 17 that deals with memory visibility and concurrency.
I am also assuming that you do not have reference leaks (I.e. you do not have a reference to the object before the object constructor is finished).
Final field. I'll just quote the above page on this, chapter 17.5:
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.
Volatile. Again, I will just quote the JLS:
A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent reads of v by any thread (where "subsequent" is defined according to the synchronization order).
Hence, assuming your Thread
got access to the object after it finished the constructor, it will see the correct value. Note, this means you will likely need to make a volatile as well.
By definition, it is guaranteed to be visible if there is a Happens-before
relationship between the read and the write. Otherwise it may happen that you see an uninitialized value. What constitutes a Happens-before
relationship? Again, the JLS chapter 17 specifies this, in particular:
Hence there can be two situations:
A a = new A();
Thread t = new MyThread(a);
t.start();
Where MyThread
saves the instance of A and uses that. In this case, the thread is created after a
, and start()
is called after it is created. Hence visibility is guaranteed, even if x
is non-volatile. However, visibility of further changes to x
is not guaranteed.
Situation 2:
This is a little more difficult to code up, but:
Main creates two Threads and immediately starts them, and has a single non-volatile field of type A.
ThreadA creates A and writes it to the shared field.
ThreadB loops through a while until the field is populated and then prints out x.
In this case, even though there is a HB between the write to x and the write to the shared field, there is no HB between read and write of the shared field. Hence there is no guarantee of the visibility of write to x.
As promised - if you put a synchronized block around the write to x in either of these 2 cases, it will not affect the outcome, since there is nothing else locking on the monitor. Locking and unlocking the same monitor creates a synchronization action, and hence create a HB relationship.