Regardless of the processor, JVM, compiler will ensure that the program is correct, as far as possible to optimize the efficiency of instruction execution, such as command rearrangement operations. In order to ensure the correctness of the execution of the procedure, the Happens-before principle stipulated in JMM must be followed.
In the Java Memory Model (JMM), if the execution result of one operation needs to be visible to another operation, then two operations must have a happens-before relationship. The principle of happens-before is very important, it is the main basis to judge whether the data is competitive, whether the thread is safe or not, and to ensure the visibility under the multi-threading environment, this principle can solve all the conflicts that may exist in the concurrency operation.
The Happens-before principle consists of single-threaded sequence rules, locking rules, volatile variable visibility rules, transitive rules, thread initiation, interrupts, terminating join rules, object finalization rules (initialization is done first in its destruction operation)
The Happens-before principle is defined as follows:
1. If one operation Happens-before another operation, the result of the first operation will be visible to the second operation, and the order of execution of the first operation is preceded by the second operation.
2. The existence of a happens-before relationship between two operations does not necessarily mean that it must be performed in the order established by the Happens-before principle. This reordering is not illegal if the execution result after reordering is consistent with the results performed by the happens-before relationship.
Here is the happens-before principle rule:
- Program Order rules: Within a thread, in the Order of code, written in front of the operation first occurs in the operation after writing;
- Locking rule: A unlock operation occurs after the face of the same lock amount lock operation;
- Volatile variable rule: The write operation of a variable precedes the read operation of the variable;
- Delivery rule: If operation a precedes operation B, and Operation B precedes Operation C, it can be concluded that operation a precedes operation C;
- Thread Initiation rule: the Start () method of the thread object takes precedence over each action of this thread;
- Thread break rule: the invocation of the thread interrupt () method occurs when the code of the interrupted thread detects that the interrupt event occurred;
- Thread termination rule: All operations in a thread occur first in the thread termination detection, and we can detect that the thread has terminated execution by means of the Thread.Join () method end, Thread.isalive () return value.
- Object Finalization rule: Initialization of an object occurs at the beginning of his finalize () method;
Let's take a closer look at each of the above rules (excerpt from the in-depth understanding of Java Virtual Machine, chapter 12th):
Program Order rules : The result of a piece of code executing in a single thread is ordered. Note that the results are executed because the virtual machine, the processor will reorder the instructions (the reordering will be described in more detail later). Although it is reordered, it does not affect the execution results of the program, so the results of the final execution of the program are consistent with the results of the sequential execution. Therefore, this rule is only valid for single thread, and cannot guarantee correctness in multi-threaded environment.
Locking Rules : This rule is better understood, whether in a single-threaded environment or a multithreaded environment, a lock is locked, you must first perform the unlock operation before the lock operation.
volatile Variable rule : This is a more important rule, which indicates that volatile guarantees thread visibility. Popular point is that if a thread first writes a volatile variable, and then a thread reads the variable, the write operation must be Happens-before read operation.
Delivery Rules : The Happens-before principle has transitivity, namely a happens-before B, b happens-before C, then a happens-before c
thread Initiation Rule : Assuming thread a executes Threadb.start () to start thread B during execution, thread A's modifications to the shared variable are guaranteed to be visible to thread B after the next thread B starts execution.
thread Termination Rule : Assume that thread A is in the process of executing, by making threadb.join () wait for thread B to terminate, then thread B is visible after the modification of the shared variable is queued to return after terminating.
The above eight are native Java rules that satisfy the happens-before relationship, but we can deduce from them other rules that satisfy Happens-before:
- An operation that puts an element into a thread-safe queue happens-before The action of removing this element from the queue
- The operation of putting an element into a thread-safe container happens-before The action of removing this element from the container
- Reciprocal operation on Countdownlatch Happens-before countdownlatch#await () operation
- Release the semaphore license Operation Happens-before get the license action
- The future represents all operations of the task Happens-before future#get () operation
- Submit a runnable or callable action to executor Happens-before task to start the operation
Here again Happens-before concept: If the two operation does not exist in the above (8 + 6) any one by one happens-before rules, then these two operations are not guaranteed by the order, the JVM can be re-ordering the two operations. If operation a Happens-before action B, then operation A's in-memory operation is visible to Operation B.
The Happens-before of the Java memory model
Talk about Java Happens-before principles