java memory model (JSR-133 memory model)

definition:

The Java Memory Model ( JMM ) is defined in the Java Virtual Machine Specification , which is used to shield the memory access differences of various hardware and operating systems, so that Java programs can achieve consistent concurrent effects on various platforms , JMM specifies how the Java virtual machine and computer memory work together: it specifies how and when a thread can see the value of shared variables modified by other threads, and how to access shared variables synchronously when necessary.

JMM mainly includes expansion threads, working memory, and main memory to interact. The three major characteristics of the Java memory model include: atomicity, visibility, and order

Inter-thread communication under the JMM model:

 

1) Thread A flushes the updated shared variables in local memory A to main memory.

2) Thread B goes to main memory to read the shared variable that thread A has updated before.

The Java memory model stipulates that all variables are stored in the main memory. Each thread has its own working memory. The working memory of the thread saves the copy of the variables used by the thread to the main memory. The thread has all the variables Operations (reading, writing) must be performed in the working memory, and the variables in the main memory cannot be directly read or written. Different threads cannot directly access variables in each other's working memory, and communication between threads needs to be completed in main memory

 

Reorder:

Reordering refers to a means by which the compiler and processor reorder the instruction sequence in order to optimize program performance. Divided into: compiler-optimized reordering , instruction-level parallel reordering , and memory system reordering

When reordering, the compiler and processor will abide by the data dependency, and the compiler and processor will not change the execution order of the two operations with data dependency (for example: a=1 b=a will not reorder). (The data dependency mentioned here only refers to the sequence of instructions executed in a single processor and the operations executed in a single thread. The data dependency between different processors and between different threads is not considered by the compiler and the processor)

Reordering may cause memory visibility issues in multithreaded programs. For processor reordering, JMM's processor reordering rules require the Java compiler to insert specific types of memory barriers (Memory Barriers, Intel called Memory Fence) instructions when generating instruction sequences, and use memory barrier instructions to prohibit specific types of Processor reordering. By prohibiting specific types of compiler reordering and processor reordering, it provides programmers with consistent memory visibility guarantees.

happens-before: JSR-133 uses the happens-before concept to illustrate memory visibility between operations. In JMM, if the execution result of an operation needs to be visible to another operation, there must be a happens-before relationship between the two operations. (The two operations here are between one thread or between different threads) happens-before only requires that the previous operation is visible to one operation, and the order of the previous operation is before the second

The happens-before rules are as follows:

1) Thread order rule: every operation in a thread, happens-before and any subsequent operations in the thread

2) Monitor lock rule: unlock a lock, happens-before and then lock the lock

3) Volatile variable rules: write to a volatile domain, happens-before any subsequent reading of this volatile domain

4) Transitivity: If A happens-before B, and B happens-before C, then A happens-before C

as-if-serial semantics:

No matter how you reorder, the result of a single-threaded program cannot be changed. Compilers and processors must comply with as-if-serial semantics

To give an example:

The data dependence of the above three operations is shown in the following figure

It can be seen that there is no data dependency between A and B. There are two possibilities for the execution order of the program, ABC or BAC, and the execution result is 3.14

Here, the as-if-serial semantics protects single-threaded programs so that programmers don't need to worry about reordering to interfere with them.

According to the happens-before program sequence rules, there are 3 happens-before relations in the above example:

1)A  happens-before B

2)B happens-before C

3)A happens-before C

Here A happens-before B, but B can be ranked before A in actual execution (the second case above). If A happens-before B, the Java memory model does not require that A must be executed before B. The Java memory model only requires that the execution result of the previous operation is visible to the next operation, and the previous operation is ordered before the second operation. Here, the execution result of operation A does not need to be visible to operation B, so in this case, the Java memory model believes that this reordering is not illegal.

volatile keyword:

Used to modify shared variables (class member variables, class static member variables), the semantics in the java memory model are as follows:

1) A thread modifies the value of a volatile variable, and this new value is immediately visible to other threads

2) The read and write operations of a single volatile variable are atomic, and compound operations (such as i++) are not atomic

3) Reordering of instructions is prohibited

final keyword:

Regarding the semantics of final in the java memory model:

1) The final modified variable is an immutable variable. As long as the object is constructed correctly (no this escape occurs), no synchronization measures are required to ensure that any thread can read the value of the variable after it is initialized in the constructor

2) Write to a final field in the constructor, and then assign the reference of the constructed object to a reference variable. The two operations cannot be reordered

3) The first time you read a reference to an object that contains a final field", and, then, the first time you read the final field of the object, the two operations cannot be reordered (assignment first, then call)

4) JMM forbids the compiler to reorder the writes of final domains outside of the constructor

☆About this escape: A simple understanding of this escape means that other threads refer to objects that have not yet been constructed, and they have to visit other people's variables, and then something incredible occurs~

 

Guess you like

Origin blog.csdn.net/qq_42407917/article/details/111056638