当前位置:网站首页>Nucleic acid detection: let me understand the principle of AQS

Nucleic acid detection: let me understand the principle of AQS

2021-01-23 21:15:28 Call practice

The Spring Festival is getting closer , The epidemic is getting worse and worse , But I can't stop calling lian to bring his family back home ( hubei ) The urge to reunite . Respond to the country's request to do Nucleic acid detection 了 .
image.png

An exclusive lock


In the morning, Jiaolian took a family of three to Nanjing First Hospital for nucleic acid testing , The little sister of the nurse stood at the gate of the hospital and told us that there were more people , No matter adults or children , We need to wait in line for doctors to collect saliva for testing ,OK, Now let's use the code + Let's see how the three members of our family line up !

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author :jiaolian
 * @date :Created in 2021-01-22 10:33
 * @description: Exclusive lock test 
 * @modified By:
 *  official account : It's called practice 
 */
public class ExclusiveLockTest {

    private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    private static ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();

    // The hospital 
    private static class Hospital {

        private String name;

        public Hospital(String name) {
            this.name = name;
        }

        // Nucleic acid testing, queuing testing 
        public void checkUp() {
            try {
                writeLock.lock();
                System.out.println(Thread.currentThread().getName()+" We're doing nucleic acid testing ");
                // Nucleic acid process ... Uncomfortable ...
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                writeLock.unlock();
            }
        }
    }


    public static void main(String[] args) throws InterruptedException {
        Hospital hospital = new Hospital(" Nanjing First Hospital ");
        Thread JLWife = new Thread(()->hospital.checkUp()," It's called wife training ");
        JLWife.start();
        // sleep 100 Millisecond is to let the three members of a family queue up in order to detect 
        Thread.sleep(100);
        Thread JLSon = new Thread(()->hospital.checkUp()," It's called Lianzi ");
        JLSon.start();
        Thread.sleep(100);
        Thread JL = new Thread(()->hospital.checkUp()," It's called practice ");
        JL.start();
    }
}

Code above : Start three threads in the main thread to queue at the hospital gate , Ladies first , Wife training is at the top of the list , In the middle is the child called Lian , Finally, it's called practicing yourself . Let's assume that the next nucleic acid test needs 3 second . We use exclusive locks in the code , Exclusive lock can be understood as a hospital with only one doctor , A doctor can only do nucleic acid for one person at the same time , So we need to queue up one by one to detect , So it takes a total of 9 second , Nucleic acid testing can be done . The code logic is still relatively simple , And what we described in our previous article synchronized Empathy . Let's describe it with a graph !
image.png

AQS The full name is AbstractQueueSynchroniz, Means queue synchronizer , It's essentially a two-way linked list , stay AQS Each thread inside is encapsulated as a Node node , Each node is added by tailing . In addition, nodes also encapsulate state information , For example, exclusive or shared , For example, the above case means exclusive Node, The doctor himself is a shared resource , stay AQS Inside, it's called state, use int Type said , All threads will go through CAS In the same way state. Thread got the lock , It's self increasing , Threads that don't grab locks will block and wait for the opportunity to wake up . Here's the picture : Abstract according to our understanding AQS The internal structure of .
image.png
** As described above , Everyone to see AQS No, it does Node Encapsulating threads , Then the thread is first come first served ( Except for unfair locks ) It's a two-way linked list ! I wrote about unfair lock before 《 Line up for dinner 》 The case is also described by simple examples . If you are interested in children's shoes, you can have a look !
**
**

Shared lock


The above process of making nucleic acid is executed synchronously , It's called exclusive lock . What does shared lock mean ? Now the only way to train children is 3 year , We can't do nucleic acid detection independently , Miss nurse, I feel the same , It is observed that jiaolianzi is behind jiaolianwife , Let them do nucleic acid tests at the same time . This kind of simultaneous manipulation of nucleic acids , It's equivalent to getting medical resources at the same time , We call it a shared lock . Here's our test code .

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author :jiaolian
 * @date :Created in 2021-01-21 19:54
 * @description: Shared lock test 
 * @modified By:
 *  official account : It's called practice 
 */
public class SharedLockTest {

    private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    private static ReentrantReadWriteLock.ReadLock readLock = lock.readLock();

    // The hospital 
    private static class Hospital {

        private String name;

        public Hospital(String name) {
            this.name = name;
        }

        // Nucleic acid testing, queuing testing 
        public void checkUp() {
            try {
                readLock.lock();
                System.out.println(Thread.currentThread().getName()+" We're doing nucleic acid testing ");
                // Nucleic acid process ... Uncomfortable ...
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                readLock.unlock();
            }
        }
    }


    public static void main(String[] args) throws InterruptedException {
        Hospital hospital = new Hospital(" Nanjing First Hospital ");
        Thread JLWife = new Thread(()->hospital.checkUp()," It's called wife training ");
        JLWife.start();
        // sleep 100 Millisecond is to let the three members of a family queue up in order to detect 
        Thread.sleep(100);
        Thread JLSon = new Thread(()->hospital.checkUp()," It's called Lianzi ");
        JLSon.start();
        /*Thread.sleep(100);
        Thread JL = new Thread(()->hospital.checkUp()," It's called practice ");
        JL.start();*/
    }
    
}

The above code we use ReentrantReadWriteLock.ReadLock As a read lock , Start on the main thread “ It's called wife training ” and “ It's called practice ” Two threads , Originally, mother and son needed 6 What can be done in seconds , Now it's just a matter of 3 It can be done in seconds , The advantage of shared lock is high efficiency . Here's the picture , yes AQS At some point inside Node Node status . Compare with the picture above ,Node The state of is changed to shared state , These nodes can share doctor resources at the same time
image.png

synchronized Lock does not respond to interrupt


/**
 * @author :jiaolian
 * @date :Created in 2020-12-31 18:17
 * @description:sync Do not respond to interrupt 
 * @modified By:
 *  official account : It's called practice 
 */
public class SynchronizedInterrputedTest {

    private static class MyService {

        public synchronized void lockInterrupt() {
            try {
                System.out.println(Thread.currentThread().getName()+"  Got the lock ");
                while (true) {
                   //System.out.println();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyService myService = new MyService();
        // Start the thread first A, Let thread A Have the lock first 
        Thread threadA = new Thread(()->{
            myService.lockInterrupt();
        });
        threadA.start();
        Thread.sleep(1000);
        // Start thread B, interrupt ,synchronized Do not respond to interrupt !
        Thread threadB = new Thread(()->{
            myService.lockInterrupt();
        });
        threadB.start();
        Thread.sleep(1000);
        threadB.interrupt();
    }
}

As the above code : Start... First A Threads , Let thread A Have the lock first , sleep 1 Second to start the thread B It's Jean B The thread is in a runnable state , Partition 1 Interrupt in seconds B Threads . The output on the console is as follows :A Thread got lock , wait for 2 Seconds later, the console did not immediately output an error message , The program has not been finished , explain synchronized Lock does not respond to interrupt , need B After the thread obtains the lock, it will output the thread interrupt error message !
image.png

AQS In response to interrupt


Often do comparison, knowledge will be integrated , stay Lock Provide lock and lockInterruptibly Two ways to get locks , among lock Methods and synchronized It doesn't respond to interruptions , Let's take a look at lockInterruptibly What does response interrupt mean . Let's use nucleic acid as an example .

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author :jiaolian
 * @date :Created in 2021-01-22 15:18
 * @description:AQS Response interrupt code test 
 * @modified By:
 *  official account : It's called practice 
 */
public class AQSInterrputedTest {

    private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    private static ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();

    // The hospital 
    private static class Hospital {

        private String name;

        public Hospital(String name) {
            this.name = name;
        }

        // Nucleic acid testing, queuing testing 
        public void checkUp() {
            try {
                writeLock.lockInterruptibly();
                System.out.println(Thread.currentThread().getName()+" We're doing nucleic acid testing ");
                // Nucleic acid process ... Uncomfortable ...
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                writeLock.unlock();
            }
        }
    }


    public static void main(String[] args) throws InterruptedException {
        Hospital hospital = new Hospital(" Nanjing First Hospital ");
        Thread JLWife = new Thread(()->hospital.checkUp()," It's called wife training ");
        JLWife.start();
        // sleep 100 Millisecond is to let the three members of a family queue up in order to detect 
        Thread.sleep(100);
        Thread JLSon = new Thread(()->hospital.checkUp()," It's called Lianzi ");
        JLSon.start();
        Thread.sleep(100);
        Thread JL = new Thread(()->hospital.checkUp()," It's called practice ");
        JL.start();
        // wait for 1 second , Interrupt is called thread 
        System.out.println(" Miss nurse wants to have a private chat with Jiaolian !");
        Thread.sleep(1000);
        JL.interrupt();
    }
}

Code above : The three members of the Jiaolian family use exclusive locks to queue up for nucleic acids , Tell me to wait for a second , Miss nurse wants to have a private chat with Jiaolian ! What would my little sister think , So call practice immediately interrupted this nucleic acid detection , Note that Immediately interrupt . The results of console printing are as follows : Both the wife calling thread and the child calling thread have done the same thing , But Jiaolian failed ! Because it was interrupted by the nurse's little sister , The results are shown in the following figure . So we can come to the conclusion that , stay aqs The middle lock can respond to interrupt . Now, if you lockInterruptibly Method instead lock What happens to the method , If it's this way , Little sister, please tease me again , Call practice to get the lock first , That is to say, Jiaolian has come to the doctor to prepare for nucleic acid therapy , My little sister suddenly said she had something to ask for , In the end, Jiaolian didn't do it , When things like this happen , It can only be said that the little sister is intentional , Cute girl Too bad 了 . About lock Method does not respond to interrupt test, you can test under their own . See if I'm wronged The nurse's little sister .
We can come to a conclusion : stay aqs If a thread is acquiring a lock or in a waiting state , Another thread interrupts the thread , Responding to an interrupt means that the thread immediately interrupts , Not responding to interrupts means that the thread needs to acquire a lock before it interrupts .
image.png
image.png

Condition queue


There may be some disappointments in life . The long hour of waiting in line finally passed , It's our turn to prepare for nucleic acid , You say? Not angry , Every time I ask my wife to go out, I bring my ID card , But I forgot to go home this time ? Let's use the code to see what happened in the process of making nucleic acid ? How to deal with it !

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author :jiaolian
 * @date :Created in 2021-01-22 16:10
 * @description: Conditional queue test 
 * @modified By:
 *  official account : It's called practice 
 */
public class ConditionTest {

    private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    private static ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();

    // Condition queue 
    private static Condition condition = writeLock.newCondition();

    // The hospital 
    private static class Hospital {

        private String name;

        public Hospital(String name) {
            this.name = name;
        }

        // Nucleic acid testing, queuing testing 
        public void checkUp(boolean isIdCard) {
            try {
                writeLock.lock();
                validateIdCard(isIdCard);
                System.out.println(Thread.currentThread().getName()+" We're doing nucleic acid testing ");
                // Nucleic acid process ... Uncomfortable ...
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                writeLock.unlock();
                System.out.println(Thread.currentThread().getName()+" Nucleic acid testing is complete ");
            }
        }

        // Verify identity information ;
        private void validateIdCard(boolean isIdCard) {
            // If there's no identity , Need to wait 
            if (!isIdCard) {
                try {
                    System.out.println(Thread.currentThread().getName()+" I forgot to bring my ID card ");
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        // Inform all who are waiting 
        public void singleAll() {
            try {
                writeLock.lock();
                condition.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                writeLock.unlock();
            }
        }

    }


    public static void main(String[] args) throws InterruptedException {
        Hospital hospital = new Hospital(" Nanjing First Hospital ");
        Thread.currentThread().setName(" Nurse little sister ");
        Thread JLWife = new Thread(()->{
            hospital.checkUp(false);
            }," It's called wife training ");
        JLWife.start();
        // sleep 100 Millisecond is to let the three members of a family queue up in order to detect 
        Thread.sleep(100);
        Thread JLSon = new Thread(()->hospital.checkUp(true)," It's called Lianzi ");
        JLSon.start();
        Thread.sleep(100);
        Thread JL = new Thread(()->{
            hospital.checkUp(true);
        }," It's called practice ");
        JL.start();
        // Wait for the thread to finish executing 
        JL.join();
        hospital.singleAll();
    }

}

Code above : A family needs to queue up to get the exclusive lock , Ask Lian wife to prepare nucleic acid first , The little sister of the nurse said she had to brush her ID card before she could go in , Call practice wife suddenly recall , I forgot my ID card when I was in a hurry , What can I do , Need to queue up again ? It's scary to call wife training , The nurse said , How about this , You go home and get it , Wait for Lianzi , Let's finish the test first , I'll arrange for you to go in and do the nucleic acid , So you don't have to queue up again , That's what this code means . Let's take a look at the execution results, as shown in the figure below , Consistent with our analysis , The place with the red circle at the end of the picture below is called practice wife, and finally complete the nucleic acid test . So let's see AQS The process of internal experience .
image.png

Here's the picture , When you ask your wife to get the lock first , I forgot to bring my ID card await Method releases the lock held , And think of yourself as node The node is placed at the end of the condition queue , The condition queue is empty , So there is only one thread called Wife Training in the condition queue , Then the nurse will release the resource of nucleic acid doctor to the next waiting person , It's called sub thread , Empathy , After the caller finishes executing and releases the lock, it will wake up the caller thread , The bottom layer is made of LockSupport.unpark To complete the wake-up operation , It's equivalent to the basic series wait/notify/notifyAll Other methods . When the thread is finished , There are no threads left behind , Nurse little sister calls singleAll Method to wake up the calling thread of the conditional queue , To join the AQS Tail of , Waiting for execution . The conditional queue is a one-way linked list , One AQS Can pass newCondition() Corresponding to multiple condition queues . Here we don't test with code alone .
image.png

summary


Today we use code + picture + The way of the story illustrates AQS Important concepts , I hope it will help you , I can't write it completely , At the same time, there are many things that need to be corrected , I hope you can correct me and comment on it , Years ago this time will continue to output to achieve AQS Advanced lock , Such as :ReentrantLock, Thread pool, these concepts, etc . Finally, please pay attention to those you like . I am a It's called practice 【 official account 】, Call and practice .

Be careful : This story is made up by myself , For your reference only . I hope everyone can go home and get together during the new year !
tempImage1611306633088.gif

版权声明
本文为[Call practice]所创,转载请带上原文链接,感谢
https://chowdera.com/2021/01/20210123211427616N.html

随机推荐