繁体   English   中英

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

[英]Does a non-volatile variable need synchronized?

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

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

当第二个线程正在执行时:

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

synchronized块之外。

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

如果第一个线程首先执行 values[i]= 58,是否可以保证如果第二个线程稍晚执行,即使第二个线程在同步块之外读取 values[i] ,第二个线程的 if 也读取 58?

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

不保证上述行为。 这种“可见性”的保证实际上是发生在关系的主题:

避免内存一致性错误的关键是理解happens-before 关系 这种关系只是保证一个特定语句写入的内存对另一个特定语句可见。

Happens-before 关系( 根据 JLS )可以这样实现:

  1. 线程中的每个操作都发生在该线程中按程序顺序稍后出现的每个操作之前。
  2. 监视器的解锁(同步块或方法退出)发生在同一监视器的每个后续锁定(同步块或方法入口)之前。 并且因为happens-before 关系是可传递的,线程在解锁之前的所有操作都发生在该监控的任何线程锁定之后的所有操作之前。
  3. 对 volatile 字段的写入发生在每次后续读取同一字段之前。 易失性字段的写入和读取具有与进入和退出监视器类似的内存一致性影响,但不需要互斥锁定。
  4. 对启动线程的调用发生在已启动线程中的任何操作之前。
  5. 线程中的所有操作都发生在任何其他线程从该线程上的连接成功返回之前。

因此,在您的特定情况下,您实际上需要使用共享监视器或AtomicIntegerArray进行同步,以便线程安全地访问数组; volatile修饰符不会有帮助,因为它只影响指向数组的变量,而不影响数组的元素(更详细的解释)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM