Volatile keyword for Java concurrency

Time:2020-11-20

introduction

When it comes to multithreading, I think the most important thing is to understand the concept of a critical region.

Volatile keyword for Java concurrency

For example, there are 1 girl (critical area) and 49 boys (thread) in a class. The goal of boys is to have a girl, which means there will be competition (thread safety). It is extended to the actual situation, such as adding or subtracting a number. Because there is only one operation object, thread safety problems will occur in multi-threaded environment. By understanding the concept of critical region, we can have a good awareness of multithreading problems.

Jav memory model (JMM)

When it comes to multithreading, you should understand the abstract schematic diagram of Java Memory Model (JMM)
Volatile keyword for Java concurrency
When thread a and thread B are executing, they will read the shared variables (critical section), and then copy a copy to their own local memory for subsequent operations.
The JMM model is a specification, just like the java interface. JMM involves three issues: atomicity, visibility, and orderliness.
So called atomicity. That is to say, whether the execution of a thread will be affected by other threads. He can’t be interrupted. for instance:

int i=1

This statement is atomic in JMM. Whether it is executed by one thread or by multiple threads, the read I is equal to 1. What is non atomicity? In principle, if java code is atomic, there should be no thread problem. In fact, JMM specifies that some statements are atomic. For example, non atomicity:

i ++;

This operation is not atomic. Because it contains three operations: first, read the value of I; second, add 1 to I; thirdly, assign the result back to I and update the value of I.
So called visibility. Visibility means that if a value is changed in thread a, thread B will immediately know the result.
The so-called order. The so-called order value is the order of semantic meaning. That is, the order of the code may change. Because there is an instruction reordering mechanism. The so-called instruction rearrangement, he will change the code execution order, in order to make the CPU more efficient. In order to prevent reordering errors, JMM has a happen before rule, which restricts those statements to be executed first and those statements to be executed after.
Happen-before:
The principle of program sequence: ensuring the seriality of semantics within a thread
Volatile principle: volatile variables are written before they are read
Lock rule: Lock first and then unlock
Transitivity: if a is prior to B and B is prior to C, then a must precede C
The thread’s start method precedes each of its operations
All operations of the thread precede the termination of the thread
The constructor of the object executes and ends before the finalize() method.

volatile

To get to the point, volatile can guarantee the visibility and order of variables (critical region), but it can’t guarantee atomicity. for instance:

public class VolatileTest implements Runnable{
    private static VolatileTest volatileTest = new VolatileTest();
    private  static volatile int i= 0;
    public static void main(String[] args) throws InterruptedException {
        for (int j = 0; j < 20; j++) {
            Thread a = new Thread(new VolatileTest());
            Thread b = new Thread(new VolatileTest());
            a.start();b.start();
            a.join();b.join();
            System.out.print(i+"&&");
        }

    }
    
    @Override
    public void run() {
        for (int j = 0; j < 1000; j++) {
            i++;
        }
    }

}

//Output results
// 2000&&4000&&5852&&7852&&9852&&11852&&13655&&15655&&17655&&19655&&21306     
//&&22566&&24566&&26189&&28189&&30189&&32189&&34189&&36189&&38089&&

Some results show that there is a problem. Although I has added the volatile keyword, it shows that volatile keyword cannot guarantee the atomicity of I + +.

What scenario is suitable for volatile keyword

  1. Lightweight “read write lock” strategy
private volatile int value;
public int getValue(){ return value;}
public synchronized void doubleValue(){ value = value*value; }

2. Singleton mode (double check lock mechanism)

private volatile static Singleton instace;   
Public static singleton getinstance() {// does not use the synchronization method, but synchronizes the method block
    //The first null check takes advantage of volatile's inter thread visibility, without locking and improving performance    
    if(instance == null){            
        synchronized( Singleton.class ){// locks class objects and blocks other threads
            //A second null check to ensure that duplicate instances are not created       
            if(instance == null){       
                Instance = new singleton(); // prohibit reordering
            }  
        }           
    }  
    return instance;

reference resources

Chinese version of modern operating system (3rd Edition)
Java high concurrency programming
The art of Java Concurrent Programming

If my article helps you, you can pay attention to my WeChat official account. I will share the article with you at the first time.

Volatile keyword for Java concurrency