Mar*_*tin 51 java concurrency multithreading java-memory-model
在Java Concurrency In Practice一书中,我们被告知可以通过编译器,JVM在运行时甚至由处理器重新排序程序的指令.因此,我们应该假设执行的程序不会以与我们在源代码中指定的顺序完全相同的顺序执行其指令.
但是,讨论Java内存模型的最后一章提供了一个先前发生的规则列表,指出了JVM保留了哪些指令排序.这些规则中的第一条是:
我相信"程序顺序"是指源代码.
我的问题:假设这个规则,我想知道什么指令可能实际重新排序.
"行动"定义如下:
Java内存模型是根据操作指定的,包括对变量的读取和写入,监视器的锁定和解锁,以及启动和连接线程.JMM定义了在程序中的所有操作之前调用的部分排序.为了保证执行动作B的线程可以看到动作A的结果(A和B是否出现在不同的线程中),必须在A和B之间的关系之前发生.在没有发生之前在两个之间进行排序操作,JVM可以随意重新排序.
其他提到的订单规则是:
ass*_*ias 56
程序顺序规则的关键点是:在一个线程中.
想象一下这个简单的程序(所有变量最初为0):
T1:
x = 5;
y = 6;
Run Code Online (Sandbox Code Playgroud)
T2:
if (y == 6) System.out.println(x);
Run Code Online (Sandbox Code Playgroud)
从T1的角度来看,执行必须与在x(程序顺序)之后分配的y一致.然而,从T2的角度来看,情况并非如此,T2可能会打印0.
T1实际上允许首先分配y,因为2个分配是独立的,交换它们不会影响T1的执行.
通过适当的同步,T2将始终打印5或不打印.
编辑
你似乎误解了程序顺序的含义.程序订单规则归结为:
如果
x并且y是同一个线程的动作并且在程序顺序x之前y,那么hb(x, y)(即x发生在之前y).
发生 - 之前在JMM中具有非常特定的含义.特别是,它不意味着y=6必须之后x=5在T1从挂钟透视.它只表示T1执行的动作序列必须与该顺序一致.您还可以参考JLS 17.4.5:
应该注意的是,两个动作之间存在的先发生关系并不一定意味着它们必须在实现中以该顺序发生.如果重新排序产生的结果与合法执行一致,则不是非法的.
在上面给出的示例中,您将同意从T1的角度(即在单线程程序中),x=5;y=6;与y=6;x=5;您不读取值一致.在T1中,保证下一行的语句可以查看这两个操作,无论它们执行的顺序如何.
| 归档时间: |
|
| 查看次数: |
11340 次 |
| 最近记录: |