class C {
private int x;
public C(int v) {
this.x = v;
}
public synchronized int get() {
return this.x;
}
public synchronized void set(int v) {
this.x = v;
}
}
(For the actual question as it was worded, the short answer is, "yes")
The question was one I get a lot. He asked how one thread can safely read the initial write of v to x. That is to say, if we have:
Thread 1:
globalRef = new C(5);
Thread 2:
C ref = globalRef;
if (ref != null) {
int r1 = ref.x;
}
How can we change this code to guarantee that the read in Thread 2 will see the value 5 for x (assuming that ref is not null)?
Let's back up for a minute, and talk about why, in the code as written, the read in Thread 2 will not see the value 5 for x. Under the Java memory model, for one thread to be guaranteed to see an update made to a variable by another thread, there must be a happens-before relationship between the update and the read. This means that sometime after the write, there must be an action that performs what we call a "release", and sometime before the read, there must be an action that performs a corresponding "acquire".
The easiest way to get a release and a corresponding acquire is to use locking on the same variable. In this case, we would do something like this:
Thread 1:
synchronized (C.class) {
globalRef = new C(5);
}
Thread 2:
synchronized (C.class) {
C ref = globalRef;
if (ref != null) {
int r1 = ref.x;
}
}
There is a release when the lock is released at the end of Thread 1, and an acquire when the lock is subsequently acquired at the beginning of Thread 2. This provides the guarantee that the updates that happen-before the release will be seen by the reads that happen-after the acquire.
For the really wonky -- what could happen? Well, we have
globalRef = new C(5);
which is really:
localRef = <allocate>;
localRef.x = 5;
globalRef = localRef;
There's no dependency between the second and third lines there, so we could easily have:
localRef = <allocate>;
globalRef = localRef;
localRef.x = 5;
And another thread could read globalRef and see the reference to the object before x is assigned the value 5.
Next post -- why this explanation is bad, bad, bad! Any guesses?