编程语言
首页 > 编程语言> > java中的指令重新排序和发生之前的关系

java中的指令重新排序和发生之前的关系

作者:互联网

参见英文答案 > How to understand happens-before consistent                                    4个
在Java Concurrency In Practice一书中,我们被告知可以通过编译器,JVM在运行时甚至由处理器重新排序程序的指令.因此,我们应该假设执行的程序不会以与我们在源代码中指定的顺序完全相同的顺序执行其指令.

但是,讨论Java内存模型的最后一章提供了一个先前发生的规则列表,指出了JVM保留了哪些指令排序.这些规则中的第一条是:

>“程序顺序规则.线程中的每个操作都发生在程序顺序后面的该线程中的每个操作之前.”

我相信“程序顺序”是指源代码.

我的问题:假设这个规则,我想知道什么指令可能实际重新排序.

“行动”定义如下:

The Java Memory Model is specified in terms of actions, which include reads and writes to variables, locks and unlocks of monitors, and starting and joining with threads. The JMM defines a partial ordering called happens before on all actions within the program. To guarantee that the thread executing action B can see the results of action A (whether or not A and B occur in different threads), there must be a happens before relationship between A and B. In the absence of a happens before ordering between two operations, the JVM is free to reorder them as it pleases.

其他提到的订单规则是:

>监控锁定规则.监视器锁定上的解锁发生在同一监视器锁定的每个后续锁定之前.
>易变变量规则.对每个后续读取同一字段之前发生对易失性字段的写入.
>线程启动规则.线程上对Thread.start的调用发生在启动线程中的每个操作之前.
>线程终止规则.线程中的任何操作都发生在任何其他线程检测到该线程已终止之前,可以通过成功从Thread.join返回,也可以通过Thread.isAlive返回false.
>中断规则.另一个线程上的线程调用中断发生在被中断的线程检测到中断之前(通过抛出InterruptedException,或者调用isInterrupted或中断).
>终结者规则.对象的构造函数的结束发生在该对象的终结器的开始之前.
>传递性.如果A发生在B之前,B发生在C之前,那么A发生在C之前.

解决方法:

程序顺序规则的关键点是:在一个线程中.

想象一下这个简单的程序(所有变量最初为0):

T1:

x = 5;
y = 6;

T2:

if (y == 6) System.out.println(x);

从T1的角度来看,执行必​​须与在x(程序顺序)之后分配的y一致.然而,从T2的角度来看,情况并非如此,T2可能会打印0.

T1实际上允许首先分配y,因为2个分配是独立的,交换它们不会影响T1的执行.

通过适当的同步,T2将始终打印5或不打印.

编辑

你似乎误解了程序顺序的含义. The program order rule boils down to

If x and y are actions of the same thread and x comes before y in program order, then hb(x, y) (i.e. x happens-before y).

发生 – 之前在JMM中具有非常特定的含义.特别地,并不意味着从壁钟的角度来看,在T1中x = 5之后必须是y = 6.它只表示T1执行的动作序列必须与该顺序一致.您也可以参考JLS 17.4.5

It should be noted that the presence of a happens-before relationship between two actions does not necessarily imply that they have to take place in that order in an implementation. If the reordering produces results consistent with a legal execution, it is not illegal.

在我上面给出的例子中,你会同意从T1的角度来看(即在单线程程序中),x = 5; y = 6;与y = 6一致; x = 5;因为你没有阅读这些值.在T1中,保证下一行的语句可以查看这两个操作,无论它们执行的顺序如何.

标签:java-memory-model,java,multithreading,concurrency
来源: https://codeday.me/bug/20190926/1820676.html