我的问题是指使用ReentrantLock是否保证字段的可见性与synchronized关键字提供的方面相同。
例如,在以下类 A 中,字段 sharedData 不需要声明为volatile,因为使用了synchronized关键字。
class A
{
private double sharedData;
public synchronized void method()
{
double temp = sharedData;
temp *= 2.5;
sharedData = temp + 1;
}
}
对于使用ReentrantLock的下一个示例,是否必须在该字段上使用volatile关键字?
class B
{
private final ReentrantLock lock = new ReentrantLock();
private volatile double sharedData;
public void method()
{
lock.lock();
try
{
double temp = sharedData;
temp *= 2.5;
sharedData = temp + 1;
}
finally
{
lock.unlock();
}
}
}
我知道无论如何使用volatile关键字只会造成微不足道的性能损失,但我仍然希望正确编码。
答案 0 :(得分:31)
没有波动性是安全的。 ReentrantLock
实施Lock
,docs for Lock
包含此内容:
所有
Lock
实施都必须强制执行 相同的内存同步 由内置提供的语义 监视器锁,如Java中所述 语言规范,第三版 (17.4记忆模型):
- 成功的
lock
操作有 相同的记忆同步效果 一个成功的Lock
行动。- 成功
unlock
操作具有相同的内存 同步效果为 成功的Unlock
行动。