[Java] Please talk about the characteristics of volatile? Why can it guarantee the visibility of variables to all threads? What are its features?

Preface

volatile is a built-in keyword in java, and it is a lightweight synchronization mechanism provided by the java virtual machine

  • Ensure visibility
  • No guarantee of atomicity
  • Disable command rearrangement

1. What is the role of volatile?

Volatile is a lightweight synchronized that generally functions as a variable and ensures memory visibility during multi-processor development. Compared with the synchronized keyword, the volatile keyword has lower execution cost and higher efficiency.

2. What are the characteristics of volatile?

The three characteristics of concurrent programming are visibility, order and atomicity. Generally speaking, volatile can ensure visibility and orderliness.

  • Visibility: volatile can ensure the visibility of shared variables when different threads operate on them. That is, when one thread modifies a shared variable, another thread can read the modified value of the shared variable.
  • Orderliness: volatile guarantees orderliness by prohibiting instruction reordering.
  • Atomicity: Atomicity can be guaranteed for reading and writing of a single volatile modified variable, but atomicity cannot be guaranteed for compound operations such as i++. What this sentence basically means is that volatile is no longer atomic.

3. Why does it guarantee the visibility of variables to all threads?

In computer programs, thread safety issues can occur when multiple threads access the same variable at the same time, one of which is the visibility issue of the variable. This means that after one thread modifies the value of a variable, other threads cannot immediately perceive the change, resulting in inconsistent behavior of the program.

To solve this problem, Java provides a keyword volatile. Variables declared using the volatile keyword have the following characteristics:

  1. Visibility: For a write operation of a volatile variable, the JVM will immediately flush the modified value back to the main memory instead of just keeping it in the local cache. This way, other threads will be able to see the latest value of the variable, thus avoiding visibility issues.

  2. Prohibition of instruction rearrangement: The volatile keyword can also prohibit the JVM from reordering and optimizing instructions. In the absence of the volatile keyword, the JVM may rearrange instructions in order to improve performance, resulting in unexpected behavior of the program. For variables declared with the volatile keyword, the JVM will ensure that the execution order of the instructions is consistent with the code order of the program, thereby avoiding this problem.

Next, we use a piece of code to demonstrate how the volatile keyword ensures visibility:

public class VolatileDemo {
    
    
    private volatile boolean flag = false;

    public void setFlag() {
    
    
        flag = true;
    }

    public void printFlag() {
    
    
        System.out.println("flag = " + flag);
    }

    public static void main(String[] args) {
    
    
        final VolatileDemo demo = new VolatileDemo();

        new Thread(() -> {
    
    
            try {
    
    
                Thread.sleep(1000); // 模拟线程1执行时间
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            demo.setFlag();
        }).start();

        new Thread(() -> {
    
    
            while (!demo.flag) {
    
     // 如果flag不是volatile,该循环可能会一直执行下去
                // do nothing
            }
            demo.printFlag();
        }).start();
    }
}

In this code, we declare a boolean volatile variable named flag. After the program starts, we start two threads. Thread 1 will set the value of flag to true after 1 second, and thread 2 will wait in a loop until the flag becomes true. Since the flag is of volatile type, thread 2 can correctly perceive the change of the flag, and print out the corresponding information after the flag becomes true. If the flag is not a volatile type, thread 2 may wait forever, because it cannot perceive the change of the flag, which will lead to wrong results in the program.

It should be noted that although the volatile keyword can guarantee visibility and prohibit instruction rearrangement, it cannot guarantee atomicity. That is to say, if a variable is accessed by multiple threads at the same time, and these threads all modify it, then using the volatile keyword does not guarantee the correctness of the program. At this time, you need to use other thread synchronization mechanisms, such as the synchronized keyword or the Lock interface.

Guess you like

Origin blog.csdn.net/u011397981/article/details/132753955