在实践中的Java并发一书中,我们多次被告知,我们的程序的指令可以由编译器、JVM在运行时重新排序,甚至可以由处理器重新排序。因此,我们应该假设,执行的程序不会按照与我们在源代码中指定的顺序完全相同的顺序执行其指令。
但是,最后一章讨论Java模型提供了一个happens-before规则列表,指示JVM保留了哪些指令顺序。这些规则中的第一条是:
我相信“程序顺序”指的是源代码。
我的问题:假设这个规则,我想知道什么指令实际上可能被重新排序。
“行动”的定义如下:
Java内存模型是根据操作指定的,包括对变量的读和写、监视器的锁和解锁,以及线程的启动和连接。JMM定义了程序中所有操作之前发生的偏序。为了确保执行操作B的线程能够看到操作A的结果(无论A和B是否发生在不同的线程中),必须在A和B之间的关系之前发生a。如果在两个操作之间排序之前没有发生,JVM可以随意重新排序它们。
提及的其他订单规则如下:
发布于 2013-05-18 21:56:27
程序顺序规则的关键点是:线程中的。
想象一下这个简单的程序(最初所有变量都是0):
T1:
x = 5;
y = 6;T2:
if (y == 6) System.out.println(x);从T1的角度来看,执行必须与y在x(程序顺序)之后被分配一致。然而,从T2的角度来看,情况并不一定如此,T2可能会打印0。
实际上允许T1首先分配y,因为两个分配是独立的,并且交换它们不影响t1的执行。
有了适当的同步,T2将始终打印5或不打印。
编辑
你似乎误解了节目顺序的含义。The program order rule boils down to
如果
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中)可以看到这两个操作,而不管它们的执行顺序如何。
https://stackoverflow.com/questions/16213443
复制相似问题