C# Java和C中易失性语义背后的原因是什么#
C#和Java都定义了这一点C# Java和C中易失性语义背后的原因是什么#,c#,java,multithreading,multiprocessing,volatile,C#,Java,Multithreading,Multiprocessing,Volatile,C#和Java都定义了这一点 *易失性读取具有获取语义 *易失性写入具有发布语义 我的问题是: 这是定义volatile的唯一正确方法吗 如果没有,如果语义颠倒,情况会有很大的不同吗,即 volatile读取具有释放语义 易失性写入具有获取语义 acquire/release语义的威力不在于其他线程多久能看到volatile字段本身新写入的值,而在于volatile操作在不同线程之间建立“先发生后发生”关系的方式。如果线程a读取一个易失性字段,并在另一个线程B中看到一个写入该字段的值,那
*易失性读取具有获取语义
*易失性写入具有发布语义
我的问题是:
- volatile读取具有释放语义
- 易失性写入具有获取语义
acquire/release语义的威力不在于其他线程多久能看到volatile字段本身新写入的值,而在于volatile操作在不同线程之间建立“先发生后发生”关系的方式。如果线程a读取一个易失性字段,并在另一个线程B中看到一个写入该字段的值,那么线程a也保证在执行易失性写入之前看到线程B写入其他(不一定是易失性)变量的值。这看起来像缓存刷新,但仅从读取volatile的线程的角度来看,其他不接触volatile字段的线程没有关于B的排序保证,并且可能会看到其早期的一些非volatile写入,但如果编译器/JIT如此倾向,则不会看到其他线程
监视器获取/释放的特征类似于它们的诱导发生在关系之前-一个线程在监视器释放之前的操作保证在另一个线程后续获取同一监视器之后可见。volatile为您提供了与监视器同步相同的排序保证,但没有阻塞。volatile语义背后的推理源于,它是根据操作指定的:
- 读取和写入变量
- 监视器的锁定和解锁
- 用螺纹开始和连接
- 锁的获取和释放
- 读取和写入volatile变量
volatile
来源:Java在哪里定义这个?我以前从未听说过它。对于主要根据虚拟机定义的语言,像CPU缓存这样特定的东西会觉得不合适。有趣的文档:Doug Lea(Java concurrent team),正如@sarnold所暗示的,您正在将语义需求与实现细节混为一谈。碰巧CPU缓存可能需要刷新以满足易失性读取(虽然不一定如此),但这只是如何强制执行易失性读取定义的一个细节。CPU缓存最重要的架构是Alpha。在所有使用多个CPU/内核的现代幸存体系结构上,CPU缓存在硬件上使用了一些不同的CPU。因此,刷新或刷新CPU缓存只会降低性能,不会作为同步机制使用。这是volatile的获取和释放语义的一个很好的解释。但为什么线程A也必须看到线程B的所有非易失性写操作呢。提供了一个很好的解释。基本上,它使volatile更加有用,因为它们实际上适用于设置volatile标志以表示特定操作已完成的情况——另一个读取该标志的线程可以知道该操作已完成,而不可能看到某些部分完成的中间状态;我慢慢地开始学习更多关于记忆模型的知识,这有助于巩固我的理解。