9

有什么理由在这段代码中同时使用 volatile 和 synchronized 吗?

public class Helper {
  private volatile int n;
  private final Object lock = new Object();
  public Helper(int n) {
    this.n = n;
  }

  public void setN(int value) {
    synchronized (lock) {
      n = value;
    }
  }
}

类助手必须是线程安全的。我从“Java Concurrency Guidelines”一书中得到了这个例子,但仍然不清楚:在这个例子中同时使用 volatile 和 synchronized 的原因是什么?

4

3 回答 3

7

这个例子的目的是指出在这种情况下syncronized没有volatile是不够的,因为对象可以不安全地发布(即没有volatilein Foo):

如果 Foo 类中的 helper 字段未声明为 volatile,则应将 n 字段声明为 volatile,以便在 n 的初始化和 Helper 写入 helper 字段之间建立起之前的关系。这符合指南“VNA06-J. 不要假定声明对象引用 volatile 可以保证其成员的可见性”(第 35 页)。仅当调用者(Foo 类)不能被信任声明辅助函数 volatile 时才需要这样做。

没错,但他们选择了一个不好的例子来演示它,因为volatile在这种情况下没有同步就足够了。

于 2012-04-12T12:07:44.747 回答
1

没有必要将同步块放在值的变化周围;从 Java 5 开始,这是对 volatile 变量“自动”完成的。我认为在 Java 5 之前,情况不一定如此。

于 2012-04-12T11:52:58.107 回答
0

我猜想使用 volatile 是因为在构造函数中设置了 'n'

于 2012-04-12T11:51:21.047 回答