编程知识 cdmana.com

The use of Java Multithread volatile

volatile keyword

The main effect :

​ 1. Ensure visibility between data .

​ 2. Disable instruction reordering .

1. visibility

2. Do a little test

public class VolatileTest implements Runnable {
    // When it comes to false End of thread at 
    private static /*volatile*/ boolean flag = true;
    private static int value = 100;
    @Override
    public void run() {
        // TODO Auto-generated method stub

        while(flag) {
            value++;
            //System.out.println(value);// You can cancel the comment and try 
        }
        System.out.println(Thread.currentThread().getName()+" end ");
    }
    public static void main(String[] args) throws InterruptedException {
        new Thread(new VolatileTest() ).start();
        Thread.sleep(1000);
        new Thread(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                flag = false;
                System.out.println(Thread.currentThread().getName()+" end ");
            }
        }).start();
        Thread.sleep(1000);
        System.out.println(Thread.currentThread().getName()+" end ");
        System.out.println("flag="+flag);
    }

}

result :

Thread-1 end 
main end 
flag=false

We can find out , The second thread will flag Change to false, But the first thread doesn't stop running .

1. Multithreaded memory model

volatile Memory model .png

3. Why? ?

From the first picture we can see that , Each thread has a working memory , Thread runtime , He reads data from main memory to working memory , And then in working memory , The execution is finished save To working memory . But other threads are not aware of changes in main memory , Don't know the main memory flag Turned into false, So I didn't update my workspace flag( Because there is no operation to let him go to the main memory to read data ), Lead to flag by true, So the loop can't stop .

4.volatile The role of : Force it to read main memory , Not the workspace , Multiple threads use the same space , It ensures visibility .

5.volatile It guarantees visibility, but it doesn't guarantee atomicity . Other operations are needed to achieve .

If you will flag Of volatile add .

result :

Thread-1 end 
Thread-0 end 
main end 
flag=false

2. Disable instruction reordering ( Orderliness )

volatile prohibit jvm And the processor volatile Reorder the modified instructions , But the instructions before and after the modifier are not specified .

What is reordering :

​ Under single thread :jvm In order to improve the efficiency of execution , We will optimize our code , Change the position of our command , But there is a premise for replacement , That is, the logic does not change under a single thread , such as :

int a = 1;
int b = 2;
int c = a + b;
// Replace with 
int b = 2;
int a = 1;
int c = a + b;

This replacement will not change the result ( Single thread ).

At the same time cpu Come on , In order to meet the problem of efficiency , It also reorders our instructions , Improve cpu Assembly line The efficiency of .

Reorder rules :

int a = 1;
int b = 2;
volatile int c = 3;
int d = 4;
int f = 6;

volatile Reordering can be disabled , But only for cosmetic commands , For the above program ,a,b No modification , therefore ,a,b You can reorder , meanwhile d,f It's fine too , however ab and df There will be no reordering , because volatile Generate Memory barrier .

(1)volatile Insert a... Before the write operation StoreStore barrier . Make sure it's going on volatile Before writing, all the previous normal write operations have been flushed to memory .

(2)volatile Insert a... After the write operation StoreLoad barrier . avoid volatile Write operations are similar to what might follow volatile The read and write operations are reordered .

(3)volatile Insert a... After the read operation LoadLoad barrier . avoid volatile The read operation is reordered with the following common read operation .

(4)volatile Insert a... After the read operation LoadStore barrier . avoid volatile The read operation is reordered with the following common write operation .

Simply speaking ,volatile The preceding instructions are not reordered with the following instructions , Running at the same time volatile When decorating , All the previous code has been executed .

Let's take an example of reordering :

public class Disorder {
    private static int x = 0, y = 0;
    private static int a = 0, b = 0;

    public static void main(String[] args) throws InterruptedException {
        int count = 0;
        long start = System.currentTimeMillis();
        while(true){
            count++;
            x = 0; y = 0;
            a = 0; b = 0;
            Thread one = new Thread(() -> {
                a = 1;
                x = b;
            });
            Thread other = new Thread(() -> {
                b = 1;
                y = a;
            });
            one.start();other.start();
            one.join();other.join();
            if (x == 0 && y ==0){
                long end = System.currentTimeMillis();
                System.out.println(" The number of times the program runs :"+count);
                System.out.println(" Program time consuming :"+(end-start));
                break;
            }
        }
    }
}

Join in , We think that the program is executed line by line , That is, the order will not change .

situation 1(one) situation 1(other) situation 2(one) situation 2(other) situation 3(one) situation 3(other)
a = 1 a = 1 a = 1
x = b b = 1 b = 1
b = 1 x = b y = a
y = a y = a x = b
result a=1
x=0
b=1
y=1
a=1
x=1
b=1
y=1
a=1
x=1
b=1
y=1
situation 4(one) situation 4(other) situation 5(one) situation 5(other) situation 6(one) situation 6(other)
b = 1 b = 1 b = 1
a = 1 a = 1 y = a
x = b y = a a = 1
y = a x = b x = b
result a=1
x=1
b=1
y=1
a=1
x=1
b=1
y=1
a=1
x=1
b=1
y=0

In the above order , It can be seen that there will never be x =0 and y = 0 At the same time , Then the program has no results .

But running the program :

 The number of times the program runs :5130
 Program time consuming :2453

Program successfully exited , It means that there is xy Zero at the same time . This means that the instructions of a thread are not executed in order , The order is out of order .

版权声明
本文为[Super salted fish]所创,转载请带上原文链接,感谢
https://cdmana.com/2021/01/20210131130618342p.html

Scroll to Top