通过ReentrantLock访问的字段是否需要volatile关键字?

Mat*_*ord 28 java concurrency locking volatile reentrancy

我的问题是指使用ReentrantLock是否保证字段的可见性与synchronized关键字提供的方面相同.

例如,在下面的类A中,当使用synchronized关键字时,字段sharedData不需要声明为volatile.

class A 
{
  private double sharedData;

  public synchronized void method() 
  {
    double temp = sharedData;
    temp *= 2.5;
    sharedData = temp + 1;
  } 
}
Run Code Online (Sandbox Code Playgroud)

但是对于使用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();
    }
  } 
}
Run Code Online (Sandbox Code Playgroud)

我知道无论如何使用volatile关键字只会造成极小的性能损失,但我仍然希望正确编码.

Jon*_*eet 32

它没有波动性是安全的.ReentrantLock实现Lock,以及包括此的文档Lock:

所有Lock实现必须强制执行内置监视器锁提供的相同内存同步语义,如Java语言规范,第三版(17.4内存模型)中所述:

  • 成功的lock操作与成功的操作具有相同的内存同步效果Lock.
  • 成功的unlock操作与成功的 操作具有相同的内存同步效果Unlock.