Java volatile 需要同步访问吗?

Java volatile necessary with synchronized access?

在下面的情况下,volatile是多余的吗?删除 volatile 会有什么不同吗?或者,离开 volatile 但删除 synchronized 块和 synchronized 修饰符在这里会有什么不同吗?

private volatile boolean registered;

synchronized boolean registered() {
  return registered;
}

void setRegistered(boolean registered) {
  synchronized (this) {
    this.registered = registered;
  }
}

不,除非您有其他未显示的访问权限,否则 registered 没有 volatile 也可以。

删除 volatile 会略微加快代码速度,我认为。但我认为删除 volatile 的主要好处是它为维护者清理了代码。

在这种情况下,volatile和我能看到的同步方法没有区别,所以使用一个或另一个。 (除了同步方法使您用来保护 registered 字段 public 的对象外,这可能是好的也可能是坏的。私有的 volatile 将同步锁保密。)


为了澄清最后的陈述,如果您有这样的class:

public class Reg {
    private boolean registered;

    synchronized boolean registered() {
      return registered;
    }

    void setRegistered(boolean registered) {
      synchronized (this) {
        this.registered = registered;
      }
    }
}

然后创建一个新实例:

public class Test {
  public static Reg reg;
  public void static main( String... args ) {
     reg = new Reg();
     synchronized( reg ) {
            // do stuff
     }
  }
}

Test 中的锁被持有时,任何其他试图访问 reg.registered() 的人都将阻塞,直到该锁被释放。锁定 public 给任何可以看到该对象的人。这可能是好事也可能是坏事。它允许其他 classes 控制对你的方法的访问,这对原子性有好处,但它也可能将一些线程控制烘焙到源代码库中,在那里它遍布而不是仅仅被一个 [=36] 封装=].好和坏。可能还有其他例子可以说明为什么这可以是好事也可以是坏事,这只是一个。