Whyissynchronizationorderdefinedastotalorderoverallofthesynchronizationactions?
While studying Java Memory Model, I was confused by the definition of synchronization order (SO). It is said that SO is a total order over all of the synchronization actions (SA) of an execution. But what is the point of talking about all SA of an execution? I can't figure out how this might be useful to me. How can I think about all SA? I understand the meaning of the following statement:
For each thread t, the synchronization order of the synchronization
actions in t is consistent with the program order of t.
该语句的用处显而易见,我可以轻松使用它。但是 SO 的定义对我来说还不清楚。因此,当涉及到多个线程的 SO 时,我无法弄清楚如何使用它。这让我很担心。您如何理解 SO 以及您在编写程序时如何使用它?
回答
SO 不是您每天都要处理的事情。它只是构建happens-before 关系的基础。
在happens-before 关系中涉及到一些命令。
有程序顺序 (PO):因此在应用任何优化之前,Java 源代码指定的单个线程执行加载/存储的顺序。程序顺序为单个线程的所有加载/存储创建总顺序。但它是一个偏序,因为它没有对不同线程的加载/存储进行排序。
然后是同步顺序 (SO):它是所有同步操作(锁获取/释放、易失性加载/存储等)的总顺序。因为每个同步操作都是原子的,它们自动形成一个全序。所以它甚至会命令释放锁 A 和获取锁 B。 SO 与 PO 一致。
然后我们有同步(SW)顺序:SW 是 SO 的子顺序,因此它只捕获同步关系。例如,如果在 SO 中对 X 的易失性写入在对 X 的易失性读取之前,那么同步关系将对这 2 个进行排序。它实际上会对 X 的写入与 X 的所有后续读取进行排序。但与 SO 不同的是,它不会命令例如 X 的易失性写入和 Y 的易失性读取。SW 也将与 PO 一致。
发生之前的顺序被定义为 PO 和 SW 联合的传递闭包。
注 1:SW 和 SO 需要与 PO 一致的原因是我们不希望 SW/SO 说 a->b 而 PO 说 b->a。因为这会导致发生之前关系中的循环,并且会由于因果循环而使其无效。
注2:为什么同步指令会创建一个总订单?好; 他们没有。但是我们可以假设存在一个全序。如果 CPU1 正在执行易失性存储 A,而 CPU2 正在执行易失性存储 B(不同的变量),那么 A、B 不可能有因果关系,因此 A-/->B 和 B-/->A(不不会发生)。所以我们现在有 2 个没有相互排序的动作。很酷的事情是我们可以选择任何订单,因为没有人可以证明否则。一个更具技术性的论点是 SO 是 DAG,并且每个 DAG 总是至少有 1 个拓扑排序,这是一个全序。