28

我的问题是关于使用 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 关键字只会对性能造成很小的影响,但我仍然想正确编码。

4

1 回答 1

32

没有波动是安全的。ReentrantLockimplements Lock,并且文档Lock包括:

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

  • 成功的操作与成功lock的操作具有相同的内存同步效果Lock
  • 成功 的操作与成功unlock的操作具有相同的内存同步效果Unlock
于 2009-10-15T06:24:06.377 回答