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

时间:2009-10-15 06:18:36

标签: java concurrency locking volatile reentrancy

我的问题是指使用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关键字只会造成微不足道的性能损失,但我仍然希望正确编码。

1 个答案:

答案 0 :(得分:31)

没有波动性是安全的。 ReentrantLock实施Lockdocs for Lock包含此内容:

  

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

     
      
  • 成功的lock操作有   相同的记忆同步效果   一个成功的Lock行动。
  •   
  • 成功   unlock操作具有相同的内存   同步效果为   成功的Unlock行动。
  •