In the below code will Java ensure that latest copy of a is visible to the thread which calls getAB()?
I understand that the values returned by getAB() might not be the same as set by setAB, but will Java ensure that the value of a seen by other thread will always either be more recent or consistent with the value of b?
public class Pair {
private int a;
private int b;
public Pair() {
super();
}
public void setAB(int a, int b) {
this.a = a;
synchronized (this) {
this.b = b;
}
}
public int[] getAB() {
int[] arr = new int[2];
arr[0] = a;
synchronized (this) {
arr[1] = b;
}
return arr;
}
}
Followup question: what happens if we move the arr[0] = a; statement to after the synchronized block?
Like this ...
public int[] getAB() {
int[] arr = new int[2];
synchronized (this) {
arr[1] = b;
}
arr[0] = a;
return arr;
}
Yes it does ... assuming the mutex has been acquired by the next thread.
However. In your example
getABis usingabefore it has synchronized onthis, soarr[0] = acould assign a stale value.Assuming that
setABis called beforegetAB, the happens before relationships in your example will be:and separately
From this we can deduce that
but we cannot deduce that
Then you move
arr[0] = a;to after thesynchronizedblock, the updated value ofais now guaranteed to be visible.I won't reproduce the full "happens before analysis", but now we get
and we can deduce that
Having said this, it is generally NOT recommended that you write code that relies on careful analysis of happens before relationships etcetera. It is better to use the higher level synchronization classes, or (as in this case) just do all of the reading and writing of shared variables inside the
synchronizedblock.(Generally speaking, the performance benefit you get from clever implementations of concurrency is usually tiny compared to overall application performance. And the long term cost of finding and fixing Heisenbugs caused by subtle synchronization code flaws can be huge.)