Three characteristics and the principle of "first come first" in the concurrency of Java memory model and virtual machine

Java Memory Model (JMM)

The main purpose of the Java memory model is to define the access rules of various variables in the program, that is, to focus on the low-level details of storing variable values ​​in memory and fetching variable values ​​from memory in the virtual machine. The variables here include instance fields, static fields, and elements that make up the array object, but do not include local variables and method parameters, because the latter are thread-private and will not be shared.
The Java memory model stipulates that all variables are stored in the main memory and are part of the virtual machine's memory. Each thread also has its own working memory. The working memory of the thread saves a copy of the main memory of the variable used by the thread. All operations (reading, assignment, etc.) of the variable must be performed in the working memory. Can not directly write data in main memory. Different threads cannot access the variables in each other's working memory, and the transfer of variables between threads needs to be done through the main memory.
The relationship among threads, main memory, and working memory:
Insert picture description here

Eight operations of memory interaction

  • lock (lock) the variable acting on the main memory
  • unlock (unlock) variables that act on main memory
  • read (read) the variable acting on the main memory
  • load (load) variables acting on working memory
  • use (use) variables acting on working memory
  • assign (assignment) acting on variables of working memory
  • store (storage) variables acting on working memory
  • write (write) variable acting on main memory

volatile

When a variable is defined as volatile, it has two characteristics. The first guarantees the visibility of this variable to all threads, and the second prohibits instruction reordering optimization.
Visibility : When a thread modifies the value of this variable, the new value is immediately known to other threads. Ordinary variables can only be done through main memory.
Since volatile variables can only guarantee the visibility of threads, in computing scenarios that do not meet the following two rules, it is still necessary to use locks (using synchronized, java.util.concurrent locks or atomic classes) to ensure atomicity:

  1. The result of the operation does not depend on the current value of the variable, or it can ensure that only a single thread modifies the value of the variable.
  2. Variables do not need to participate in invariant constraints with other state variables.

Three important features in concurrency

Atomicity

It can be roughly considered that the access, read and write of basic data types are all atomic (except for long and double non-atomic protocols). If you need a larger range of atomicity, you can use the synchronized keyword in the code.

Visibility

When a thread modifies the value of a shared variable, other threads can immediately discover the modification.
The Java memory model achieves visibility by synchronizing the new value back to the main memory after the variable is modified, and refreshing the variable value from the main memory before the variable is read, which relies on the main memory as the transmission medium to achieve visibility. Synchronized and final in
Java can also achieve visibility. The visibility of the synchronization code block is caused by: before unlocking a variable, the variable must be synchronized back to main memory. Visibility of final keyword: Once the field modified by final is initialized in the constructor, and the constructor does not pass the reference of "this", then other threads can see the value of the final field.

Orderliness

If you observe in this thread, all operations are in order, if you observe in another thread in another thread, all operations are out of order.

First come first

  1. Procedure order rule: the operation that is written first occurs first
  2. Monitor lock rules: For using a lock, unlock must occur before lock
  3. Volatile variable rules: A volatile write operation must occur before a volatile read operation.
  4. Thread start rule: The start() method of the Thread object occurs before every action of this thread
  5. Thread termination rule: all operations in the thread occur before the termination operation
  6. Thread interruption rule: The call to the thread interrupt() method occurs linearly when the code of the interrupted thread detects the occurrence of the interruption time
  7. Object termination rules: the initialization of an object occurs first and its finalize() method
  8. Transitivity: If A precedes B, B precedes C, then A precedes C

Guess you like

Origin blog.csdn.net/weixin_43663421/article/details/109347942