current position:Home>Java Concurrent Programming atlas learning (IV) orderliness

Java Concurrent Programming atlas learning (IV) orderliness

2022-05-15 05:18:36Peter Pan 1231

Catalog

One 、 Preface

Two 、Happens-before

1. Procedural order rules

2. volatile Variable rule

3. Transitive rules

4.  Monitor lock rules

5. start() The rules

6. join() The rules

3、 ... and 、 summary


One 、 Preface

1. As our program apes don't want to write bug influence KPI, So I hope The memory model is easy to understand 、 Easy to program . This needs to be based on a strong Memory model Come on Write code

2. As Compilers and processors I don't want outsiders to say it's slow , So I hope Memory models bind them as little as possible , They can optimize it without authorization , This needs to be based on a weak Memory model

Since caching and compile optimization cannot be completely prohibited , It would be Disable caching and compilation optimization on demand , On demand is to add some constraints , Constraints include the simple mention of... In the previous article Yes volatile,synchronized,final Three keywords , At the same time, you may have heard of Happens-Before principle ( Include can ⻅ Constraints of sex and order )

1. about Meeting Change the reordering of program execution results ,JMM Require compilers and processors This reordering must be prohibited .

2. about Can't Change the reordering of program execution results , JMM For compilers and processors Do not ask (JMM Allow this reorder )

Two 、Happens-before

Happens-before Rules are mainly used to constrain two operations , There is... Between the two operations happens-before Relationship , It does not mean that the previous operation must be performed before the next operation ,happens-before only The previous operation is required ( Results of execution ) For the latter operation, you can ⻅

Let's take a look at a small piece of code to take you step by step into Happen-Befores principle , See how Use this principle to solve can ⻅ sex and Orderliness The problem of

class ReorderExample { 
    int x = 0;
    boolean flag = false; 
    
    public void writer() {
        x = 42; //1
        flag = true; //2 
    }
    
    public void reader() { 
        if (flag) { //3
            System.out.println(x); //4 
        }
    } 
}

hypothesis A Threads execute writer Method ,B Threads execute reader Method , Printed x It could be 0, Because the code 1 and 2 No data dependencies , So it could be reordered . Threads A take flag = true Write but not for x When reassigning , Threads B Maybe it's already printed x yes 0

flag = true; //2
x=42; //1

So for flag add volatile Try the keyword

volatile boolean flag = false;

1. Procedural order rules

Every operation in a thread , happens-before Any subsequent operation in the thread The first feeling This principle is an ideal " crap ", And as mentioned above, there will be reordering Is contradictory , Note that this is an operation in a thread , In fact, it implies 「as-if-serial」 semantics : To put it bluntly, as long as the execution result is not changed , No matter what " Sort ", Are all right

2. volatile Variable rule

To a volatile Domain writing , happens-before In any follow-up to this volatile Domain reading

 

From this form The last column It can be seen that

If The second act volatile Write , No matter what the first operation is , Can't reorder , This is Ensured volatile Operations before writing will not be reordered to volatile After writing . Take the code above for example , Code 1 and 2 Will not be reordered to code 3 Behind , But the code 1 and 2 Could be reordered ( No dependency and no impact on execution results )

From this form Second to last row It can be seen that

If The first operation is volatile read , No matter what the second operation is , Can't reorder , this Ensured volatile Operations after reading will not be reordered to volatile Before reading . Take the code above say , Code 4 Is read volatile Variable , Code 5 and 6 Will not be reordered to code 4 Before

3. Transitive rules

If A happens-before B, And B happens-before C, that A happens-before C

  1. x =42 and y = 50 Happens-before flag = true , This is the rules 1
  2. Write variables ( Code 3) flag=true Happens-before Read variable ( Code 4) if(flag) , This is the rules 2
  3. According to rules 3 Transitive rules , x =42 Happens-before Read variable if(flag)

4.  Monitor lock rules

Unlocking a lock happens-before Then lock the lock

public class SynchronizedExample { 
    private int x = 0;

    public void synBlock(){
    // 1. Lock 
        synchronized (SynchronizedExample.class){
        x = 1; //  Yes x assignment  
    }
    // 3. Unlock 

    // 1. Lock 
    public synchronized void synMethod(){ 
        x = 2; //  Yes x assignment 
    }
    // 3.  Unlock 
}

First get the thread of lock , Yes x Release lock after assignment , Another gets the lock again , I'm sure I can see right x Changes in assignment , It's that simple  

5. start() The rules

If the thread A Perform the operation ThreadB.start() ( Start thread B), that A Thread ThreadB.start() operation happens-before Thread B Any operation in , in other words , The main thread A Start the child thread B after , Sub thread B You can see that the main thread is starting the sub thread B The operation of the former

public class StartExample { 
    private int x = 0;
    private int y = 1;
    private boolean flag = false;

    public static void main(String[] args) throws InterruptedException {         

        StartExample startExample = new StartExample();
        Thread thread1 = new Thread(startExample::writer, " Threads 1"); 
        startExample.x = 10;
        startExample.y = 20;
        startExample.flag = true;

        thread1.start();
        System.out.println(" End of main thread "); 
    }

    public void writer(){ 
        System.out.println("x:" + x ); 
        System.out.println("y:" + y ); 
        System.out.println("flag:" + flag );
    }
}

Threads 1 See the main thread call thread1.start() All previous assignments , Running results :

End of main thread

x:10
y:20

flag:true

6. join() The rules

If the thread A Perform the operation ThreadB.join() And return successfully , So thread B Any operation in happens-before Thread A from ThreadB.join() Operation successful return , and start The rules are just the opposite , The main thread A Wait for the child thread B complete , When a child thread B After completion , The main thread can see the sub thread B Assignment of

public class JoinExample { 
    private int x = 0;
    private int y = 1;
    private boolean flag = false;

    public static void main(String[] args) throws InterruptedException {     
        JoinExample joinExample = new JoinExample();
        Thread thread1 = new Thread(joinExample::writer, " Threads 1"); 

        thread1.start();
    
        thread1.join();

        System.out.println("x:" + joinExample.x ); 
        System.out.println("y:" + joinExample.y ); 
        System.out.println("flag:" + joinExample.flag ); 
        System.out.println(" End of main thread ");
    }
    
    public void writer(){ 
        this.x = 100;
        this.y = 200; 
        this.flag = true;
    } 
}

  Running results :

x:100
y:200 
flag:true 
 End of main thread 

3、 ... and 、 summary

  1. Happens-before The key point is to solve the problem that the result of the previous operation can ⻅

  2. start and join The rules are also One of the ways to solve the communication between main thread and sub thread

  3. From memory semantics ⻆ In terms of degree , volatile Of Write - read With the lock Release - obtain It has the same memory effect ; volatile Write and The release of the lock Have the same memory semantics ; volatile read And Lock acquisition Have the same memory semantics , volatile The solution is can ⻅ sex problem ,synchronized The solution is Atomicity problem

copyright notice
author[Peter Pan 1231],Please bring the original link to reprint, thank you.
https://en.cdmana.com/2022/131/202205111242179055.html

Random recommended