The basis of java multithreading - java memory model (JMM)

In concurrent programming, two key issues need to be dealt with: how to communicate between threads, and how to synchronize between threads. Communication refers to how threads exchange information. In imperative programming, there are two communication mechanisms between threads: memory sharing and message passing.
     Synchronization refers to the mechanism used in a program to control the relative order in which operations occur between different threads. In the shared memory concurrency model, synchronization is done explicitly. Programmers need to explicitly set the mutually exclusive execution of a certain piece of code between threads. In the concurrency model of message passing, synchronization occurs implicitly because the sending of a message must precede the receipt of a message.
     Java concurrency uses a shared memory model.
 
     The key technical points of the Java Memory Model (JMM) are built around the atomicity, orderliness, and visibility of multithreading.
 
     1. Atomicity
     Atomicity means that an operation is uninterruptible. Even when multiple threads are executing together, once an operation starts, it will not be interrupted by other threads.
     For example, for a static variable i, there are two threads assigned to it, thread A assigns it a value of 1, and thread B assigns it a value of 2, then no matter how the two threads work, i is either 1 or 2. There is no interference between threads A and B, which is a feature of atomicity and cannot be interrupted.
     However, if the long type is used (the long type is 64-bit), for a 32-bit operating system, the reading and writing of long data is not an atomic operation, that is, if multiple threads operate on a long at the same time, the The result is interference.
 
     2. Visibility
     Visibility refers to when a thread modifies the value of a shared variable, whether other threads are immediately aware of the modification. For serial programs, this problem does not exist, because the variable value is modified in any one step, and the value read in the subsequent steps must be modified.
     But not so much in parallel programs. If one thread modifies the value of a variable, other threads may not be aware of the change immediately. Thread A and thread B read variable i respectively, and then A operates on variable i. At this time, B may not know immediately.
 
     3. Ordering - Ordering
     For the execution code of a thread, we always habitually think that the execution of the code is executed sequentially from front to back. But in the case of concurrency, the execution of the program may appear out of order. The intuitive feeling is: the code behind is executed first, and the code in front is executed later. It sounds incredible, this is because the program may perform instruction rearrangement during execution, that is, the order of instructions is adjusted without affecting serial semantics to optimize the execution efficiency of the CPU (instruction rearrangement can ensure that the sequence The row semantics are consistent, but there is no way to guarantee the same semantics between threads). Regarding instruction rearrangement, I will take the time to write a special article to explain it later.
     Although the java virtual machine and the execution system will rearrange the instructions, there are still some principles that cannot be violated by the instruction rearrangement, namely the Happen-Before rule:
          A Program Order Principle: Guaranteed Semantic Seriality within a Thread
          B volatile rule: the writing of volatile variables occurs first before reading, which ensures the visibility of volatile variables (take the time to write an introduction to volatile)
          C lock rule: unlock (unlock) must happen before the subsequent lock (lock)
          D transitivity: A precedes B, B precedes C, then A must precede C
          E thread's start() method precedes each of its actions
          All operations of the F thread precede the termination of the thread (Thread.join())
          G thread's interruption (interrupt()) precedes the interrupted thread's code
          The constructor of the H object executes and ends before the finalize() method

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325256300&siteId=291194637