我粘贴了一些有关Java并发的代码:
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;
}
}
}
为什么return value;
需要同步?
return语句不是原子的吗?
答案 0 :(得分:8)
返回不需要同步。由于CountDownLatch.countDown()
直到最后一次设置该值之后才被调用,因此CountDownLatch.await()
确保在读取和返回该值之前是稳定的。
写这篇文章的开发人员可能不太确定自己在做什么(并发既困难又危险),或者更有可能的是,他在GuardedBy
上使用value
注释导致了他的构建系统在return
上发出警告,而其他一些开发人员则不必要地同步它,只是为了消除警告。
我说的是“其他开发者”,因为否则该类似乎是专门为允许getValue()
进行设置而无需锁定而继续进行的。
答案 1 :(得分:2)
return语句需要对 value 进行读取操作。
大多数 原语的读取操作是原子的,但是您要处理的是泛型,这意味着您将不知道 value 的类型。
因此,退货应保持同步。
答案 2 :(得分:2)
return value
不需要 进行同步:
value
都可以按照Java Memory Model value = newValue
happens-before done.countDown()
的方式查看其最新值。 先于 done.await()
,先于 return value
。通过传递性value = newValue
,因此先于 return value
。