One: The cache of modern computers
In the principle of computer composition, the modern computer in order to match the computer storage device read and write speed and processor speed, A cache device called cache is added between the CPU and the memory device as a buffer: the data required for the operation is copied from memory to the cache, and the CPU can read and write the cache at high speed during the operation, and the data is synchronized back to memory from the cache after the operation is completed.
The cache raises a new issue: caching consistency. Each processor has its own cache, and they share one main memory. When the operations of multiple processors are designed in the same memory area, the respective cache data will be inconsistent. Then, at the end of the respective operation, whose cache data will be synchronized back to main memory? At this point, you need to cache the consistency protocol to make multiple processors read and write to the unified memory area.
In addition to the cache, in order to make better use of the processor resources, the processor also executes the code in a disorderly sequence, finally reorganizing the results so that the results are consistent with the sequential execution.
Two: Analogy of Java memory model
The analogy with the main memory and CACHE,JVM of modern computers specifies that all variables are stored in primary RAM (analogousto the machine memory), and then each thread has its own working RAM (analogous to each processor's cache). the thread's working memory holds the copy value of the variable that the thread needs to use, and the thread runs on the CPU to read and write to the data in its own worker thread, and the data is synchronized to the main memory after the run is finished. So analogy to the computer using cache consistency protocol to solve the cache consistency problem, theJVM needs a thread synchronization mechanism to achieve multithreading to the same memory region read and write control .
In addition, in order to improve performance, the Java compiler takes command reordering (analogous to the computer's disorderly execution), and if multiple threads have statements that operate on the same memory area, it is possible that the result is not predictable because of the order reordering. Therefore, the thread synchronization mechanism is also required to achieve multithreading to read and write control of the same memory area .
Three: Data interaction between main memory and working memory
The JVM defines 8 operations to complete the data interaction between the main memory and the thread's working memory:
1:lock: Identifies the main memory variable as a thread exclusive and does not allow other threads to read and write to this variable at this time.
2:unlock: Unlocks a main memory variable.
3:read: Reads a main memory variable value into the working memory of the thread, emphasizing that it is read into the process.
4:load: Saves the read-to-variable value to the thread's working memory as a copy of the variable, emphasizing the process of saving the value that is reading in.
5:use: During thread execution, the value of the variable in the working memory is passed to the bytecode execution engine.
6:assign (Assignment): The bytecode execution engine passes the result of the operation back to the working memory and assigns it to the result variable in the working memory.
7:store: Transfers the value of the variable in the working memory to the main memory, emphasizing the process of transmission.
8:write: Writes the value of the variable passed in the store into the main memory variable, emphasizing the process of saving.
The JVM requires that the above 8 operations be atomic, that is, the data read and write operations are atomic. However, there are exceptions, namely: long, double non-atomic agreement: The two 64-bit types of data read, write operations are required two times, one read/write 32 bits, two reads/Two writes are not guaranteed atomicity.
IV: Atomicity, Visibility, order
Atomicity: The read and write operations of the basic data types are atomic, and the greater range (code block) of atomicity can be implemented with the lock, unlock operation (only one thread executes after locking, so the atomic operation is not interrupted by another thread), Performance to the code level is the use of syncrhoized synchronization blocks.
Visibility: When a thread modifies the value of a main memory variable shared by multiple threads, the other line Cheng Nen immediately know the change.
As we can see above, the JVM is changing the value of the variable in the working memory, synchronizing the new value to the main memory, and then the other thread reads the new value from the main memory to achieve visibility. Here's the difference: when the value of a normal variable changes, it does not necessarily synchronize the main memory immediately, but it will wait until the thread finishes or a period of time to synchronize, and after synchronizing back to main memory, the other thread's working memory does not necessarily read the new value immediately. Variables modified by the volatile keyword, once modified in working memory, are immediately synchronized back to main memory, and the working memory of the other thread that uses the variable immediately reads the new value from main memory. The syncrhoized keyword-modified variable can only be used by one thread at a time, so there is only one worker thread reading and writing it at a time, so it is also possible to "portrait" to achieve visibility.
Ordering: The ordering of the operation of shared data between multiple threads can be ensured by means of volatile and syncrhoized keywords. The volatile keyword prohibits command reordering, whereas the Syncrhoized keyword specifies that multiple threads can only have one thread to operate on the shared data at a time.
V: volatile keyword
A volatile variable has two characteristics: visibility, prohibit order reordering. However, volatile does not have atomic nature! The reason is that the value of the volatile variable can be alternately modified by multithreading, and the modifications include read, load, use, store, write, and so on, which are not guaranteed to be atomic.
Visibility: Variables modified by the volatile keyword, once modified in working memory, are immediately synchronized back to main memory, and the working memory of other threads that use the variable immediately reads the new value from main memory.
Prohibit command reordering: Volatile variables create a memory barrier after they are assigned: when the instruction is reordered, the following instruction cannot be queued before the memory barrier.
Memory model in Java Multi-threading