非易失性变量是否需要同步?

Does a non-volatile variable need synchronized?

考虑 2 个线程和一个数组 int[] values。 第一个线程正在执行:

synchronized (values) {
     values[i] = 58;
}

当第二个线程执行时:

if (values[i] == 58) {
}

synchronized 街区之外。

如果第一个线程先执行values[i]= 58,是否保证如果第二个线程稍晚执行,第二个线程的if读取58,即使第二个线程在 synchronized 块外读取 values[i]

If the first thread first performs values[i]= 58, is it guaranteed that if the second threads executes slightly later, that the if of the second thread reads 58 even though the second thread reads values[i] outside a synchronized block?

没有

以这种方式同步不会阻止其他线程同时对数组执行任何操作。但是,将阻止其他线程获取数组上的锁。

不保证上述行为。这样一个"visibility"的保证其实是一个happens-before关系的主题:

The key to avoiding memory consistency errors is understanding the happens-before relationship. This relationship is simply a guarantee that memory writes by one specific statement are visible to another specific statement.

happens-before 关系 (according to JLS) 可以这样实现:

  1. 线程中的每个操作都先于该线程中按程序顺序出现的每个操作之前发生。
  2. 监视器的解锁(同步块或方法退出)发生在同一监视器的每个后续锁定(同步块或方法入口)之前。并且由于先发生关系是可传递的,因此解锁之前线程的所有操作先于任何线程锁定该监视器之后的所有操作。
  3. 对可变字段的写入发生在同一字段的每次后续读取之前。 volatile 字段的写入和读取与进入和退出监视器具有相似的内存一致性效果,但不需要互斥锁定。
  4. 线程上的启动调用发生在启动线程中的任何操作之前。
  5. 一个线程中的所有操作发生在任何其他线程成功之前 returns 来自该线程上的连接。

因此,在您的特定情况下,您实际上需要使用共享监视器进行同步或 AtomicIntegerArray in order to make access to the array thread-safe; volatile modifier won't help as is, because it only affects the variable pointing to the array, not the array's elements (more detailed explanation)。