什么是Java synchronized的有效重新排序?
许多人问了类似的问题,但没有一个答案让我满意。 我非常确定的唯一两条重新排序规则如下 如下:什么是Java synchronized的有效重新排序?,java,multithreading,Java,Multithreading,许多人问了类似的问题,但没有一个答案让我满意。 我非常确定的唯一两条重新排序规则如下 如下: 同步块内的操作(或仅调用它 “关键部分”(critical section)允许重新排序,只要它符合“仿佛”序列语义 业务(包括两者) 不允许将读操作和写操作移出(重新排序)关键部分 但是,对于同步块之前或之后的操作,是否可以将其移动到关键部分?对于这个问题,我发现了一些相反的观点。例如,报告称编译器将在MonitorEnter之后和MonitorExit之前插入一些屏障: MonitorEnter
MonitorEnter
(any other needed instructions go here )
[LoadLoad] <===MB1:Inserted memory barrier
[LoadStore] <===MB2:Inserted memory barrier
(Begin of critical section)
....
(end of critical section)
[LoadStore] <===MB3:Inserted memory barrier
[StoreStore] <===MB4:Inserted memory barrier
(any other needed instructions go here )
MonitorExit
允许产生以下代码的重新排序:
根据理解1,“y=1”不能在临界段内上移,
所以我很困惑,哪一个是正确的和完整的?重新排序不关心内存障碍。即使编译器总是在任意两条指令之间插入最强的内存屏障,这些重新排序仍然是允许的 现在,给定一个指令序列,可能在从原始序列重新排序之后,编译器需要在一些指令之间插入适当的内存屏障 例如,给定一个原始指令序列
volatile store x
normal store y
这两条指令之间不需要内存屏障
但是,编译器可以选择将其重新排序为
normal store y
volatile store x
然后,两个指令之间需要一个StoreStore屏障。CPU只有一条“存储”指令,没有正常/易失性存储的概念。CPU可能有无序的存储。Java语义要求另一个CPU在volatilestorey
的影响之前不能观察到storex
的影响;因此,StoreStore用于告诉CPU按顺序存储它们
(如果编译器足够聪明,它会记住原始程序不需要y->x
的顺序,因此实际上不需要这个障碍。但假设编译器没有那么聪明。)
罗奇模型汽车旅馆-- JMM的要点是在不同线程上的指令之间建立一些(部分)顺序,以便可以定义读/写的效果。在下面的示例中
thread 1 thread 2
a1 a2
|
}b1 -----> b2{
|
c1 c2
建立同步顺序b1->b2
,可以是volatile store->volatile load
,或者监视器退出->监视器进入
。这将在订单发生之前连接a1->b1->b2->c2
由于我们需要保证a1->c2
的顺序,因此a1
不得使用b1
重新排序,c2
不得使用b2
重新排序;也就是说,蟑螂不能“退房”
另一方面,JMM希望尽可能的软弱;它没有说明
c1
和a2、b2、c2
之间的影响;因此,c1
可以使用b1
自由重新排序。类似地,a2
可以使用b2
重新排序。也就是说,蟑螂可以“签入”。即使“编译器足够聪明”,根据我的理解,编译器仍然需要在您的示例中插入Store,因为它可以防止处理器在volatile存储之前的指令和volatile存储本身之间重新排序,从而强制执行volatile存储的语义。感谢@bayou.io的详细解释!总之,我的理解是,对于MonitorEnter之前或MonitorExit之后的读写操作,可以在编译(JIT编译)期间将其移动(重新排序)到关键部分。但是,一旦编译完成,处理器就无法将移动的读写操作移出,由于编译器插入的内存障碍会被处理器所重视,对吗?假设原始程序是normalstorea;易失性存储器B
。JMM语义是,在另一个线程看到B的效果之后,它也应该看到A的效果。现在,JVM的工作是在特定的CPU体系结构上实现该语义。默认情况下,CPU可能会无序执行写操作;但它也支持一个屏障指令来禁用它。因此,在CPU上,JVM首先将保持A和B的顺序,即JVM不会重新排序;然后JVM将在A和B之间插入StoreStore,也就是说CPU不会重新排序。如果指令P;Q
不应按照JMM重新排序,第一个表将禁止JVM重新排序,第二个表将禁止CPU重新排序。综合效应为P;Q
当其他CPU观察到时,似乎不会重新排序。
volatile store x
normal store y
normal store y
volatile store x
thread 1 thread 2
a1 a2
|
}b1 -----> b2{
|
c1 c2