Correct SynchronizationIf the multi-threaded program is executed in the sequence consistency model and the program meets the requirement of data race free, the program is correctly synchronized.
The execution result of a correctly synchronized multi-threaded program is consistent with that in the sequential consistency model. Carefully understand the relationship between concepts. It's a bit difficult.
On the other hand, if the program is not correctly synchronized and the execution results are not arbitrary, it must be restricted, but the restriction cannot be too strong, because it will hinder optimization. Therefore, the Java memory model uses the Causality Requirements concept.
Causality RequirementsTo precisely define the memory model, the concept of Causality Requirements is proposed in the Java language specification. I don't know why. This concept is rarely mentioned, but I think it is very important, but it is also very confusing. In the language specification, the Well-Formed Executions concept is first defined. Many discussions on the memory model are at this layer, which includes the execution of multi-threaded programs and locks, volatile variables and execution sequence. If the execution of a multi-threaded program meets these requirements, the execution will be Well-Formed Executions. There is a series of articles in China, deep understanding of the Java memory model, which mainly describes the Java memory model. In addition, The famous Doug Lea in The field of Java concurrency also gives The JSR-133 Cookbook for Compiler Writers, which provides reference for Compiler authors and discusses this issue. However, whether the execution of a multi-threaded program by the memory model is legal depends not only on whether it is Well-Formed Executions, but also on whether the execution meets the Requirements of Causality Requirements.
The language specification specifies a constructor. If the constructor can construct the final execution result of a multi-threaded program, then this execution will meet the Requirements of Causality Requirements. The constructor starts from an empty set C0 and adds several operations each time. If all operations can be added, the constructor is constructed successfully. That is,
C0 -> C1 -> C2 -> ... -> C
C_ I is a subset of C _ (I + 1. You may have noticed that "operations can be added". What is "operations can be added? According to the language specification, each Ci corresponds to an Ei, and all Ei must meet Well-Formed Executions. That is to say, if the corresponding Ei does not meet Well-Formed Executions after you add an operation, this operation cannot be added. If your multi-threaded program cannot construct such an execution chain, the execution result is invalid.
In addition, The author of The Java Memory Model first maintained a page of The Java Memory Model. One of The entries is Causality Test Cases, which provides some small examples, so that people can understand what behaviors meet Causality Requirements and what are not satisfied. In addition, Doug Lea, well-known in The field of Java concurrency, also gives The JSR-133 Cookbook for Compiler Writers, which provides reference for Compiler authors. However, it is said that this specification is too strict in some places. Developers still develop it according to the Java language specification and virtual machine specification.