JUC Concurrency Series (2): Detailed explanation of using Condition instead of wait and notify [to achieve accurate notification wakeup]

It is not difficult to run a program; the difficult thing is how far the program can run! —— a fierce seed

Insert picture description here
JUC Concurrency Series

First acquainted with JUC concurrency series (1): what? I heard you confuse concurrency and parallelism

1. What is Condition

Condition was updated in jdk1.5, which can be used to replace the original wait and notify to achieve inter-thread cooperation, because Condition's await and signal methods are safer and more efficient.

You can see the previous in-depth multithreading series. We use the monitor method and the semaphore method to solve the problem of producers and consumers by using wait and notify .

In-depth multi-threading 15: the management method to solve the problem of producers and consumers

In-depth multi-threading sixteen: semaphore way to solve the problem of producers and consumers

2. Hand type code to achieve Condition to achieve accurate notification wake

There is a scenario where we want an output result to be executed in the order of ABC, then we use today's protagonist Condition to achieve.

2.1 Condition is not used

Before implementing the Condition to accurately notify the wake-up, first look at the code segment that does not use the Condition to output the result. (Comparing learning is more intuitive)

public class demo{
    
    
    public static void main(String[] args) {
    
    
        Data data = new Data();
       new Thread(()->{
    
    
           for (int i = 0; i < 5; i++) {
    
    
               data.testA();
           }
       },"一颗剽悍的种子A").start();
       new Thread(()->{
    
    
           for (int i = 0; i < 5; i++) {
    
    
               data.testB();
           }
       },"一颗剽悍的种子B").start();
       new Thread(()->{
    
    
           for (int i = 0; i < 5; i++) {
    
    
               data.testC();
           }
       },"一颗剽悍的种子C").start();
    }
}
class Data{
    
    
    public void testA(){
    
    
        System.out.println(Thread.currentThread().getName() + "A");
    }
    public void testB(){
    
    
        System.out.println(Thread.currentThread().getName() + "B");
    }
    public void testC(){
    
    
        System.out.println(Thread.currentThread().getName() + "C");
    }
}

operation result

You can see that the order is messed up, not in the order of execution we want.

Insert picture description here

2.2 Use Condition to achieve accurate notification wakeup

Synchronized is an exclusive lock. The process of locking and unlocking is performed automatically, which is easy to operate, but not flexible enough. ReentrantLock is also an exclusive lock, but the process of locking and unlocking needs to be done manually, which is not easy to operate, but very flexible.

Key code

Manual lock -> Judgment -> Execution -> Notification -> Manual lock

    public void testA(){
    
    
        lock.lock();
        try {
    
    
        while (num != 1){
    
    
                conditionA.await(); //等待
            }
            System.out.println(Thread.currentThread().getName() + "A");
            num++;
            conditionB.signal();    //通知
        }catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            lock.unlock();
        }
    }

All codes

public class demo{
    
    
    public static void main(String[] args) {
    
    
        Data data = new Data();
       new Thread(()->{
    
    
           for (Integer i = 0; i < 5; i++) {
    
    
               data.testA();
           }
       },"一颗剽悍的种子A").start();
       new Thread(()->{
    
    
           for (Integer i = 0; i < 5; i++) {
    
    
               data.testB();
           }
       },"一颗剽悍的种子B").start();
       new Thread(()->{
    
    
           for (Integer i = 0; i < 5; i++) {
    
    
               data.testC();
           }
       },"一颗剽悍的种子C").start();
    }
}
class Data{
    
    
    private Lock lock = new ReentrantLock();
    private Condition conditionA = lock.newCondition();
    private Condition conditionB = lock.newCondition();
    private Condition conditionC = lock.newCondition();
    private Integer num = 1;    //1 = A  2 = B 3 = C

    public void testA(){
    
    
        lock.lock();
        try {
    
    
        while (num != 1){
    
    
                conditionA.await(); //等待
            }
            System.out.println(Thread.currentThread().getName() + "A");
            num++;
            conditionB.signal();    //通知
        }catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            lock.unlock();
        }
    }
    public void testB(){
    
    
        lock.lock();
        try {
    
    
            while (num != 2){
    
    
                conditionB.await(); //等待
            }
            System.out.println(Thread.currentThread().getName() + "B");
            num++;
            conditionC.signal();    //通知
        }catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            lock.unlock();
        }
    }
    public void testC(){
    
    
        lock.lock();
        try {
    
    
            while (num != 3){
    
    
                conditionC.await(); //等待
            }
            System.out.println(Thread.currentThread().getName() + "C");
            num = 1;
            conditionA.signal();    //通知
        }catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            lock.unlock();
        }
    }
}

operation result
Insert picture description here

3. Prevent false wakeups

If you have seen the previous in-depth multithreading series or the code above, if you pay attention, you will find that we use the while judgment more than if in the judgment , because if there may be false wakeups.

So what is to prevent false wakeups?

The so-called false wakeup means that although the thread can wake up, it will not be notified, interrupted or timed out.

Four, finally

At the end, for a better reading experience, I put everything I want to say below, hehe.

I am a seed of decisions based on my will, serious share what I wrote blog has been the same creed.
If you can read this blog post, it means that we are still very destined; I hope it can bring you some help, the creation is not easy,
take away the knowledge of my article, your three consecutive leave, like, comment, follow , Is my biggest motivation.

Guess you like

Origin blog.csdn.net/A_hxy/article/details/108665139