I pasted some code about Java concurrency:
public class ValueLatch <T> {
@GuardedBy("this") private T value = null;
private final CountDownLatch done = new CountDownLatch(1);
public boolean isSet() {
return (done.getCount() == 0);
}
public synchronized void setValue(T newValue) {
if (!isSet()) {
value = newValue;
done.countDown();
}
}
public T getValue() throws InterruptedException {
done.await();
synchronized (this) {
return value;
}
}
}
Why does return value;
need to be synchronized???
Is the return statement not atomic??
The return statement needs to perform a read operation over value.
The read operation is atomic for most primitives, but you're dealing with a generic, meaning you won't know value's type.
For that reason, the return should be synchronized.
The return does not need to be synchronized. Since CountDownLatch.countDown()
is not called until after the value is set for the last time, CountDownLatch.await()
ensures that value is stable before it is read and returned.
The developer who wrote this was probably not quite sure of what he was doing (concurrency is difficult and dangerous) or, more likely, his use of the GuardedBy
annotation on value
caused his build system to emit a warning on the return
, and some other developer synchronized it unnecessarily just to make the warning go away.
I say 'some other developer', because this class otherwise seems to be specifically designed to allow getValue()
to proceed without locking once the value has been set.
return value
does not need to be synchronized:
value
is guaranteed to so see its latest value as according to the Java Memory Model value = newValue
happens-before done.countDown()
, which happens-before done.await()
, which happens-before return value
. By transitivity value = newValue
thus happens-before return value
.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With