getter 上的 volatile 和 setter 上的同步是否与两者上的同步相同?

Is volatile on getter and synchronized on setter the same as synchronized on both?

在并发程序中,这样安全吗:


private volatile int i;

public int getI() {
    return i;
}

public synchronized incrementI() {
    i++;
}

?

根据我对 synchronize 的了解,更改保证在 i 上仅适用于在同一对象上获取锁监视器的线程。 所以我认为,上面的代码是不安全的。如果为真请确认,否则请说明。 谢谢。

这段代码是线程安全的。同步方法中的更改会传递给所有线程。 由于您已将其设为易失性,因此所有线程都不会缓存它,因此将获取最新副本。

这个帖子也会有帮助Java volatile modifier and synchronized blocks

由于 Integer i 是 class 的私有实例变量,同步实例方法将起作用。您需要确保添加到 class 的所有修改 i 的方法都必须使用相同的对象监视器进行同步。

请注意 i++ 不是自动表达式,因此只有 volatile 不起作用。

您可以像这样将 AtomicInteger 用于单个值。

几乎在"JMM Pragmatics"here中给出了确切的例子。

volatile 提供 happens-before 边缘,使 setter 之前的更改对 getter 之后发生的所有事情可见,假设 getter 实际观察到设定值。 synchronized在setter中另外给出互斥,即volatile单独不保证。