Nik*_*ski 7 java multithreading synchronization jvm volatile
官方说明说,那
写入易失性字段与监视器释放具有相同的记忆效应,从易失性字段读取具有与监视器获取相同的记忆效应.
和
实际上,易失性的语义已大大加强,几乎达到了同步的程度.出于可见性的目的,每次读取或写入易失性字段的行为类似于"半"同步.
从这里开始.
这是否意味着,对volatile变量的任何写入都会使执行线程将其缓存刷新到主内存中,并且每次从volatile字段读取都会使线程从主内存重新读取其变量?
我问,因为同一文本包含此声明
重要说明:请注意,两个线程都必须访问相同的volatile变量才能正确设置before-before关系.情况并非如此,线程A在写入易失性字段f时可见的所有内容在读取易失性字段g后变为线程B可见.释放和获取必须"匹配"(即,在相同的易失性字段上执行)以具有正确的语义.
这句话让我很困惑.我知道对于使用synchronized语句定期锁定获取和释放不是这样 - 如果某个线程释放任何监视器,那么它所做的所有更改都会明显地变为所有其他线程(更新:实际上不是真的 - 请注意最佳答案).在stackoverflow上甚至有一个关于它的问题.然而据说无论出于何种原因,情况并非如此.我无法想象发生在事先保证的任何实现,它不会使其他线程看到更改,这些线程不会读取相同的volatile变量.至少想象一个实现,它与前两个引号并不矛盾.
此外,在发布这个问题之前,我做了一些研究,例如这篇文章,其中包含这个句子
执行这些指令后,所有其他线程都可以通过缓存子系统或主内存看到所有写入.
提到的指令是在写入易失性字段时发生的指令.
那重要的音符应该是什么意思?或者我错过了什么?或许这个说明是完全错误的?
回答?
在进行了一些更多的研究后,我只能在官方文档中找到关于volatile字段及其对非易失性字段变化的影响的声明:
使用volatile变量可降低内存一致性错误的风险,因为对volatile变量的任何写入都会建立与之后读取同一变量的先发生关系.这意味着对volatile变量的更改始终对其他线程可见.更重要的是,它还意味着当线程读取volatile变量时,它不仅会看到volatile的最新更改,还会看到导致更改的代码的副作用.
从这里开始.
我不知道这是否足以得出结论,这种情况发生在关系只保证读取相同的volatile的线程之前.所以现在我只能总结一下结果是不确定的.
但实际上我建议考虑线程A在写入volatile字段时所做的更改,B只有当线程B读取相同的volatile字段时,才能保证线程可见.官方消息来源的上述引言强烈暗示.
你从一个完全错误的角度来看这个问题。首先,您引用了JLSand 而不是谈论冲洗,这将是该规范的实现细节。您唯一需要依赖的绝对是 JLS,了解其他任何东西可能都不错,但不能以任何形式或形式证明规范的正确或错误。
你错误的根本地方是:
我确信这对于常规锁获取来说是不正确的......
在实践中x86,您可能是对的,但是JLS 官方 Oracle 教程要求:
当线程释放固有锁时,该操作与同一锁的任何后续获取之间会建立发生之前关系。
Happens-before 是为后续操作而建立的(如果您愿意,请阅读两个操作(如果这对您来说更简单))。一个线程释放锁,另一个线程获取锁 - 这些是后续的 ( release-acquire semantics)。
同样的事情也会发生volatile- 某个线程写入该内容,并且当其他线程通过后续读取观察到该写入时,发生之前就建立了。
| 归档时间: |
|
| 查看次数: |
152 次 |
| 最近记录: |