I. Introduction to the Java memory model
The Java merory model describes the access rules for various variables (thread-shared variables) in Java programs, as well as the underlying details of storing variables into memory and reading variables from memory in the JVM.
All variables are stored in main memory, but each thread has its own independent working memory, saving a copy of the variable used by that thread.
Article Two provisions
1. The operation of a thread on a shared variable can only be performed in a separate working memory and cannot be read or written directly in the main memory;
2. Variables in the working memory of other threads cannot be accessed directly between different threads and need to be completed through main memory.
To achieve the visibility of shared variables, two points must be guaranteed
1. Thread-Modified shared variables can be flushed from the working memory to the main memory in time;
2. Other threads can update the current value of the shared variable from main memory to working memory in time.
How Java supports visibility implementations from a language level
Synchronized Volatile
Ii. Synchronized realization of visibility
Synchronized in addition to the ability to enable code to be executed by only one thread at a time, there is also a function to achieve visibility.
Two provisions on synchronized 1. Before threads unlocked, the current value of the shared variable must be brushed to the main memory; 2. When the line Cheng, the shared variable value of the working memory is emptied and re-read from the main memory. These two rules guarantee that the operation of the shared variable before the thread is unlocked is visible to the other threads before the next lock is added.
Synchronized the process of achieving visibility
1. Obtain the mutex 2. Empty the working memory 3. Copy the latest value of the shared variable from main memory to working memory 4. Execute code 5. Update the modified variable value to main memory 6. Release lock
As-if-serial and reordering
re-order :the execution order and the order of the Code are not the same, and command reordering is the optimizations that the compiler or processor makes to improve performance. divided into compiler optimizations, processor instruction level parallel reordering, memory system reordering (optimization of read/write caching, as mentioned above)
As-if-serial: Regardless of the reordering, the results of the program execution are consistent with the results of the code order execution. (This is not to say that it is not re-ordered!) )
Java is guaranteed to be as-if-serial in a single thread.
Causes of shared variables not visible between threads and solutions 1. Thread Cross execution;Synchronized's atomic nature solves this problem.2. Reorder + Thread cross-execution (even if () and {} may be reordered, control dependencies are not reordering constraints, only data dependencies are)Synchronized's atomic nature solves this problem.3. Updated values for shared variables are not updated in time between main memory and working memorysynchronized two rules to solve this problem
Third, volatile realization of visibility
The volatile keyword guarantees the visibility of volatile variables, but does not guarantee the atomicity of the volatile variable compound operation.
How volatile is implemented by adding a memory barrier and prohibiting command reordering:
When a write operation is performed on a volatile variable, a store barrier instruction is added to the write operation, which forces the cache of the CPU write cache to be flushed to the main memory, and prevents the processor from reordering volatile variables to volatile. When a read operation is performed on a volatile variable, a load barrier instruction is added before the read operation. Forces reads from main memory on read.
In layman's terms, each time a volatile variable is accessed by a thread, it forces the value of the variable to be reread from the main memory, not from the working memory cache, forcing the thread to flush the most recent value into main memory when the value changes.
It is not guaranteed that the atomicity of volatile variable compound operations such as:p rivate volatile int a=0;a++; Not atomic operation: three-step, read the value of a, a+1; write back the value of a
But the following is an atomic operation: synchronized (this) {a++;}
In addition to synchronized, you can also use Lock:lock lock= new Reentrantlock (); Can be re-entered in the lock and then in the back: Lock.lock (); try{a++;} Finally{lock.unlock ();}
Application scenario for volatile 1. Writing to a variable does not depend on the current value is not satisfied: num++; Num=num*5 ... Satisfying: Boolean variables and so on 2. The variable is not included in the invariant with other variables, that is, when there are multiple volatile variables in the program, each independent. such as a, B; If there is a a<b such a formula, it is not satisfied.
So the scope of application of Volatie is not as large as synchronized.
Iv. comparison of synchronized and volatile
1.volatile does not need to lock, is lighter than synchronized, does not cause the thread to block. The 2.synchronized guarantees both visibility and atomicity, while volatile can guarantee visibility only.
=========================================================================== (the article was written after watching the video, thank you/HTTP// www.imooc.com/view/352)
Reprint please indicate the source, thank you!
Java multi-thread memory visibility