Detailed explanation of the volatile keyword that concurrent programming has to know

One, what is volatile

Volatile is an important keyword in Java concurrent programming. It is likened to "lightweight synchronized". Unlike synchronized, volatile can only modify variables, but cannot modify methods and code blocks.
The following is a singleton pattern implemented using the volatile keyword:

public class Singleton implements Serializable {
    
    
  private static volatile Singleton singleton;
  private Singleton() {
    
    }
  public static Singleton getSingleton() {
    
    
    if (singleton==null) {
    
             // 1
      synchronized (Singleton.class) {
    
      // 2
        if (singleton==null) {
    
         // 3
          singleton = new Singleton();// 4
        }
      }
    }
    return singleton;
  }
  private Object readResolve() {
    
     //防止序列化破坏单例模式
    return singleton;
  }
}

1. Why do singletons use the volatile keyword?

The first thing to understand is what new Singleton() does. 1. See if the class object is loaded, if not, load, parse and initialize the class; 2. The virtual machine allocates memory space, initializes the instance, 3. calls the constructor, 4. returns the address to the reference. In order to optimize the program, the cpu may perform instruction reordering, causing the instance memory to be used before it is allocated.

Suppose there are two threads A and B. Thread A executes to new Singleton(), and starts to initialize the instance object. Due to the reordering of instructions, the reference is assigned to the new operation this time, and the constructor has not been executed (not really finished. ). At this time, the time slice is over, switch to thread B to execute, thread B calls the new Singleton() method, and finds that the reference is not equal to null, it directly returns the reference address, and then thread B performs some operations, which may cause thread B to use Variables that have not been initialized.

2. What is the significance of the existence of steps 1, 2, 3, and 4 in the singleton mode?

First of all, steps 2 and 3 are to ensure singleton. Assuming that both threads A and B have executed step 2, thread A gets the lock, and execute step 3. If no instance is created at this time, thread A will execute new to create the instance, then thread A releases the lock, and thread B gets the lock and executes first Step 3. It is found that the instance has been created, and return directly. Locking consumes more resources. Step 1 is to reduce resource consumption.

Second, the characteristics of volatile

1. Prohibit instruction reordering

Instruction reordering is the JVM in order to optimize the instructions and improve the efficiency of the program, without affecting the execution results of the single-threaded program, to maximize the degree of parallelism. Instruction reordering includes compiler reordering and runtime reordering.

The volatile keyword provides a memory barrier to prevent instructions from being rearranged. When the compiler generates a bytecode file, it inserts a memory barrier in the instruction sequence to prohibit specific types of processor reordering.

JVM memory barrier insertion strategy:

  • Insert a StoreStore barrier in front of each volatile write operation, Store1; StoreStore; Store2. Before Store2 and subsequent write operations are executed, ensure that Store1 write operations are visible to other processors, ensuring orderliness and visibility;
  • Insert a StoreLoad barrier after each volatile write operation, Store1; StoreLoad; Load2. Before Load2 and subsequent read operations are executed, ensure that the write operation of Store1 is visible to other processors. Its overhead is the largest. Has the other three functions, ensuring orderliness and visibility;
  • Insert a LoadLoad barrier after each volatile read operation, Load1; LoadLoad; Load2. Before Load2 and subsequent read operations are performed, ensure that the data read by Load1 has been read;
  • Insert a LoadStore barrier after each volatile read operation, Load1; LoadStore; Store2, to ensure that the data read by Load1 has been read before Store2 and subsequent write operations are executed.

2. Ensure memory visibility

Visibility means that the reading of a volatile variable can always obtain the last write of a volatile variable by any other thread.
The realization of visibility is based on the memory semantics of volatile read and write:

  • Memory semantics of volatile writing: When writing a volatile variable, the JVM refreshes the variable value in the thread's working memory to the main memory;
  • Memory semantics of volatile reading: When reading a volatile variable, the JVM first sets the variable in the working memory to be invalid, and then obtains the latest valid value from the main memory.

Three, usage scenarios

(1) Volatile is a lightweight synchronization mechanism. The difference with synchronized is that volatile can only guarantee order and visibility, not atomicity.
(2) Volatile cannot modify the variable whose write operation depends on the current value. If the current value of a simple variable declared as volatile is related to the previous value of the variable, then the volatile keyword does not work, which means that the following expressions are not atomic operations: "count++", "count = count+1".
(3) When the variable to be accessed is already in the synchronized code block or is constant, it is not necessary to use volatile;
(4) Volatile guarantees order and shields the necessary code optimization in the JVM, so the efficiency is compared Low, so this keyword must be used only when necessary.
(5) Volatile can be used instead of synchronized in the following two scenarios:

  • The result of the operation does not depend on the current value of the variable, or it can be ensured that only a single thread will modify the value of the variable.
  • Variables do not need to participate in invariant constraints with other state variables.

Some high-frequency interview questions collected in the latest 2020 (all organized into documents), there are many dry goods, including mysql, netty, spring, thread, spring cloud, jvm, source code, algorithm and other detailed explanations, as well as detailed learning plans, interviews Question sorting, etc. For those who need to obtain these contents, please add Q like: 11604713672

Guess you like

Origin blog.csdn.net/weixin_51495453/article/details/115266601