3 回答
TA贡献1797条经验 获得超6个赞
显然,写入 l 会阻止写入 k 的重新排序,但它会阻止写入 i 和 j 的重新排序吗?
重新排序的含义并不完全清楚;看我上面的评论。
然而,在Java 5+内存模型,我们可以说,写入i
和j
所发生之前,写入l
将是另一个线程可见后已经阅读l
......只要没有写i
和j
写后l
。
这确实会限制写入i
和的指令的任何重新排序j
。具体来说,它们不能在写入后的内存写入屏障之后移动到l
,因为这可能导致它们对第二个线程不可见。
但这项禁令的范围是什么?
本身没有禁令。
您需要了解指令、重新排序和内存屏障只是实现 Java 内存模型的特定方式的细节。该模型实际上是根据保证在任何“格式良好的执行”中可见的内容来定义的。
据我了解, volatile 会阻止在使用它的块内重新排序,对吗?
实际上,没有。块不考虑。重要的是方法中语句的(程序源代码)顺序。
@Stephen C 说,volatile 保证发生在整个方法主体内部的行为之前,即使在封闭块中,但我找不到任何确认。
确认是 JLS 17.4.3。它声明如下:
在每个线程 t 执行的所有线程间动作中,t 的程序顺序是一个总顺序,它反映了根据 t 的线程内语义执行这些动作的顺序。
如果所有动作以与程序顺序一致的总顺序(执行顺序)发生,则一组动作是顺序一致的,此外,变量 v 的每次读取 r 都会看到写入 w 写入 v 的值,使得:
w 在执行顺序中排在 r 之前,并且
在执行顺序中,没有其他写入 w' 使得 w 在 w' 之前并且 w' 在 r 之前。
顺序一致性是对程序执行中的可见性和顺序的非常有力的保证。在顺序一致的执行中,所有单独的动作(例如读取和写入)都有一个与程序顺序一致的总顺序,每个单独的动作都是原子的,对每个线程都是立即可见的。
如果一个程序没有数据竞争,那么程序的所有执行都将看起来是顺序一致的。
请注意,此定义中没有提及块或范围。
TA贡献1111条经验 获得超0个赞
我很想知道 volatile 变量如何影响其他字段
易失性变量确实会影响其他字段。如果 JIT 编译器认为重新排序不会对执行输出产生任何影响,则可以对指令重新排序。因此,如果您有 6 个独立变量存储,则 JIT 可以重新排序指令。
但是,如果您将变量设为 volatile,即在您的情况下为变量l,那么 JIT 将不会在 volatile STORE 之后重新排序任何变量 STORES。我认为这是有道理的,因为在多线程程序中,如果我将变量l的值设为 4,那么我应该将i设为 1,因为在我的程序中,我是在l之前编写的,最终是程序顺序语义(如果我是没有错)。
Note that volatile variables does two things:
编译器不会在易失性存储之后重新排序任何存储/在易失性读取之前不会重新排序任何读取。
刷新加载/存储缓冲区,以便所有处理器都可以看到更改。
编辑:
这里的好博客:http : //jpbempel.blogspot.com/2013/05/volatile-and-memory-barriers.html
添加回答
举报