Visibility: A thread's modification of shared variable values can be seen by other threads in a timely manner.
The Java memory Model (JMM) 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 out variables from memory in the JVM. All variables in multiple threads are stored in main memory, and each thread has its own independent working memory, which holds a copy of the variable used by the thread (the copy of the variable in main memory). Two ways to realize the visibility of multithreading synchronized
Synchronized has two main functions in multi-threading
- Atomicity (synchronous)
- Visibility of
JMM two provisions on synchronized:
- The current value of the shared variable must be flushed to main memory before the line threads unlocked
- Line Cheng, the shared variable values in the working memory are emptied, so that the shared variable needs to be re-read from the main memory (PS: Locking is the same lock required for unlocking). Implements the visibility of shared variables.
Reorder : The compiler or processor optimizes for improved program performance.
as-if-serial: Regardless of reordering, the results of the program execution should be consistent with the results of the Code order execution (both the Java compiler runtime and the processor ensure that Java follows the as-if-serial semantics on a single thread).
Cause analysis that causes thread sharing variables to be invisible in threads:
- Atomic resolution of thread cross-execution-->synchronized
- Re-ordering atomic resolution with thread cross-execution-->synchronized
- The value of the shared variable update does not update the visibility of the-->synchronized in a timely manner between the working memory and the main memory
Volatile realization of visibility PS: can guarantee the visibility of variables, can not guarantee that the variable conforms to the atomic nature of the operation. Volatile implementation Principle Analysis:
implemented by adding memory barriers and preventing reordering optimizations
- When a write operation is performed on a volatile variable, a store barrier instruction is added after the write operation (forcing the master memory to be brushed)
- When a read operation is performed on volatile, a load barrier is added to the read operation (forcing the update from main memory to working memory)
eg:num++; contains three-step operation, volatile cannot guarantee atomicity, while multi-threaded operation, although visibility is preserved, it cannot be kept synchronized.
Solution:
- Using the Synchronized keyword
- Use the Reentrantlock lock operation (the lock internal operation needs to be performed in the try...finally. Finally, perform unlock () unlock operation)
- Using Atomicinterger
To safely use volatile variables in multiple threads, you must satisfy
- The write operation on a variable does not depend on the current variable value
- The variable is not contained in the invariant of other variables
Comparison of synchronized and volatile
- Volatile does not need to be locked, more lightweight, does not block threads
- Analysis from the perspective of visibility: volatile reading is equivalent to lock, volatile write is equivalent to unlocking
- Synchronized can satisfy both atomicity and visibility
Analysis of the visibility of Java multi-thread