1. Sum up

  • Multithreaded output loop output, is one of the concurrent programming interview frequently asked questions, to solve this kind of problem can be divided into two main solutions

  • Already plan

    • Note: a thread a condition, do not mess
    • Note:conditionApproach is toAwait () and singal ()notWait ()
  • The syn scheme

    • When you multithreadNotifyAll ()And andNotify ()Be careful to distinguish
  • A WHO variable is needed to calibrate whose turn it is to perform

  • Must first block, then output, then wake up, the order cannot change!!

    • If you print first, then block and wake up last, you may get an error the first time you print (see below).
    • inreentrantLockNext, the blocking judgment is usediforwhileCan be
    • In syn, three-thread blocking can only be determined by using while(dual-thread blocking can be used)if)
      • This is due toreentrantLockYou can let the specified thread wake up whilesynIn the case of three threads onlynotifyAll, and one of the threads needs to be blocked again

2. The two threads loop to print AB

Method of syn

public class AB_syn {
    static int count = 0;

    public static void main(String[] args) {
        Object lock = new Object();
        new Thread(() -> {
            // Enter the lock before you can control it
            synchronized (lock) {
                // Print in an infinite loop
                while (true) {
                    // If count is not equal to 0, then another thread needs to print and wait ().
                    while(count ! =0) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("A");
                    // Wake up thread 2
                    count = 1;
                    // While (count! =0) to block inside
                    lock.notify();
                }
            }
        }).start();
        new Thread(() -> {
            // Put them in the lock before you can control them
            synchronized (lock) {
                // Print in an infinite loop
                while (true) {
                    while(count ! =1) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("B");
                    count = 0; lock.notify(); } } }).start(); }}Copy the code

reentrantlock

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

public class AB_reentrylock {
    static int who = 0;

    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        Condition conditionA = lock.newCondition();
        Condition conditionB = lock.newCondition();


        new Thread(() -> {
            try {
                // Enter the lock first, then control
                lock.lock();
                while (true) {
                    while(who ! =0) {
                        conditionA.await();
                    }
                    System.out.println("A");
                    // Wake up B and queue B in AQS
                    conditionB.signal();
                    who = 1; }}catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }).start();

        new Thread(() -> {
            try {
                // Enter the lock first, then control
                lock.lock();
                while (true) {
                    while(who ! =1) {
                        conditionB.await();
                    }
                    System.out.println("B");
                    // Wake up A and queue up A in AQS
                    conditionA.signal();
                    who = 0; }}catch (Exception e) {
                e.printStackTrace();
            } finally{ lock.unlock(); } }).start(); }}Copy the code

3. Three threads print ABC

Method of syn

public class ABC_syn {
    static int who = 0;

    public static void main(String[] args) {
        Object lock = new Object();
        new Thread(() -> {
            synchronized (lock) {
                while (true) {
                    while(who ! =0) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("A");
                    who = 1;
                    lock.notifyAll();
                }
            }
        }).start();

        new Thread(() -> {
            synchronized (lock) {
                while (true) {
                    while(who ! =1) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("B");
                    who = 2;
                    lock.notifyAll();
                }
            }
        }).start();

        new Thread(() -> {
            synchronized (lock) {
                while (true) {
                    while(who ! =2) {
                        try {
                            lock.wait();

                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("C");
                    who = 0; lock.notifyAll(); } } }).start(); }}Copy the code

reentrantlock

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

public class ABC_reentrylock {
    static int count = 0;
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        lock.notifyAll();
        Condition conditionA = lock.newCondition();
        Condition conditionB = lock.newCondition();
        Condition conditionC = lock.newCondition();
        new Thread(() -> {
            try {
                // Lock and enter the concurrency control internal
                lock.lock();
                while (true) {
                    while(count ! =0) {
                        conditionA.await();
                    }
                    System.out.println("A");
                    // Enable the thread blocking conditionB to wake up
                    conditionB.signal();
                    count = 1; }}catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }).start();


        new Thread(() -> {
            try {
                // Lock and enter the concurrency control internal
                lock.lock();
                while (true) {
                    while(count ! =1) {
                        conditionB.await();
                    }
                    System.out.println("B");
                    // Enable the thread blocking conditionB to wake up
                    conditionC.signal();
                    count = 2; }}catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }

        }).start();

        new Thread(() -> {
            try {
                // Lock and enter the concurrency control internal
                lock.lock();
                while (true) {
                    while(count ! =2) {
                        conditionC.await();
                    }
                    System.out.println("C");
                    // Enable the thread blocking conditionB to wake up
                    conditionA.signal();
                    count = 0; }}catch (Exception e) {
                e.printStackTrace();
            } finally{ lock.unlock(); } }).start(); }}Copy the code

4. Why do you need to judge blocking before printing?

In this case, if thread 2 starts the execution first, it will cause the first output to be B first. In the case of three threads, there is no guarantee that the first output will be A

public class AB_syn2 {
    static int count = 0;

    public static void main(String[] args) {
        Object lock = new Object();
        new Thread(() -> {
            // Put them in the lock before you can control them
            synchronized (lock) {
                // Print in an infinite loop
                while (true) {
                    System.out.println("A");
                    // Wake up thread 2
                    count = 1;
                    lock.notify();
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        new Thread(() -> {
            // Put them in the lock before you can control them
            synchronized (lock) {
                // Print in an infinite loop
                while (true) {
                    System.out.println("B");
                    count = 0;
                    lock.notify();
                    try {
                        lock.wait();
                    } catch(InterruptedException e) { e.printStackTrace(); } } } }).start(); }}Copy the code

5. Write a deadlock

  • The four elements of a deadlock:
    • Exclusive access
    • Ask and hold
    • Do not deprive
    • Loop waiting for
  • In simple terms, two locks (AB), with one thread holding A and the other thread holding B, request each other’s resources
public classA deadlock{
    public static void main(String[] args) {
        Object A = new Object();
        Object B = new Object();
        new Thread(() -> {
            synchronized (A) {
                System.out.println("Got an A");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Try to get B after 100 milliseconds.");
                synchronized (B){
                    System.out.println("bbbb");
                }
            }
        }).start();

        new Thread(() -> {
            synchronized (B) {
                System.out.println("Got a B");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Try to get A after 100 milliseconds.");
                synchronized (A){
                    System.out.println("aaaa"); } } }).start(); }}Copy the code