官方说明说,
写入易失性字段与监视器释放具有相同的记忆效应,而从易失性字段读取与监视器获取具有相同的记忆效应。
和
实际上,volatile 的语义得到了大幅加强,几乎达到了同步的水平。出于可见性的目的,对 volatile 字段的每次读取或写入都类似于“一半”同步。
这是否意味着,对 volatile 变量的任何写入都会使执行线程将其缓存刷新到主内存中,并且每次从 volatile 字段读取都会使线程从主内存中重新读取其变量?
我问是因为完全相同的文本包含此声明
重要说明:请注意,两个线程都必须访问相同的 volatile 变量,以便正确设置happens-before 关系。线程 A 在写入 volatile 字段 f 时可见的所有内容在线程 B 读取 volatile 字段 g 后都可见,但情况并非如此。释放和获取必须“匹配”(即在同一个易失性字段上执行)以具有正确的语义。
而这个说法让我很困惑。我确信使用同步语句获取和释放常规锁不是真的 - 如果某个线程释放任何监视器,那么它所做的所有更改对所有其他线程都是可见的(更新:实际上不是真的 - 观看最佳答案)。在stackoverflow上甚至有一个关于它的问题。然而,据说无论出于何种原因,对于 volatile 字段都不是这种情况。我无法想象任何发生在保证之前的实现,它不会使其他线程、不读取相同 volatile 变量的线程可见更改。至少想象一个实现,它与前两个引号并不矛盾。
此外,在发布这个问题之前,我做了一些研究,例如这篇文章,其中包含这句话
执行这些指令后,所有写入都可以通过缓存子系统或主内存对所有其他线程可见。
提到的指令是在写入 volatile 字段时发生的指令。
那么这个重要的笔记应该是什么意思呢?或者我错过了什么?或者,也许那张纸条是完全错误的?
回答?
经过更多的研究,我只能在关于 volatile 字段及其对非 volatile 字段变化的影响的官方文档中找到这样的说法:
使用 volatile 变量可以降低内存一致性错误的风险,因为对 volatile 变量的任何写入都会与对该相同变量的后续读取建立先发生关系。这意味着对 volatile 变量的更改始终对其他线程可见。更重要的是,这也意味着当一个线程读取一个 volatile 变量时,它不仅会看到对 volatile 的最新更改,还会看到导致更改的代码的副作用。
我不知道这是否足以得出结论,只有读取相同 volatile 的线程才能保证发生之前的关系。所以现在我只能总结结果是不确定的。
但在实践中,我建议考虑 thread 所做的更改A
,当它写入 volatile 字段时,B
只有当线程B
读取相同的 volatile 字段时,才保证对线程可见。以上来自官方来源的引用强烈暗示了这一点。
aluckdog
千万里不及你
相关分类