Javaベース:100%デッドロックが発生するプログラム


マルチスレッドはJavaエンジニアがステップアップするために身につけなければならないスキルであり、面接では迂回できない一環でもあり、デッドロックはマルチスレッド同期に失敗した古典的なケースでもあり、複雑なシステムでは、デッドロックはコードレベルで静的検出と検査を行うことが難しく、ある面接官は逆方向からデッドロックプログラムを手書きで書くことができます.まず、ネットワーク上でよく見られるデッドロックプログラムを見てみましょう(問題がある可能性があります):
public class DeadLockTest {    private static Object lock1 = new Object();    private static Object lock2 = new Object();    public static void main(String[] args) {        new Thread(() -> {
            synchronized (lock1) {
                System.out.println("thread1 acquired lock1");                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("thread1 try to acquire lock2");
                synchronized (lock2) {
                    System.out.println("thread1 acquired lock2");
                }
            }
        }, "t1").start();        new Thread(() -> {
            synchronized (lock2) {
                System.out.println("thread2 acquired lock2");                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("thread2 try to acquire lock1");
                synchronized (lock1) {
                    System.out.println("thread2 acquired lock1");
                }
            }
        }, "t2").start();        
        //     
        checkDeadLock();
        System.out.println("main thread end");
    }    public static void checkDeadLock() {
        ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
        ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(1);        //     5 ,  10     
        scheduled.scheduleAtFixedRate(()->{            long[] threadIds = mxBean.findDeadlockedThreads();            if (threadIds != null) {
                System.out.println("       :");
                ThreadInfo[] threadInfos = mxBean.getThreadInfo(threadIds);                for (ThreadInfo info : threadInfos) {
                    System.out.println(info.getThreadId() + ":" + info.getThreadName());
                }
            }
        }, 5L, 10L, TimeUnit.SECONDS);
    }
}

上記のプログラムでは99.99%の場合にデッドロックが発生しますが、理論的には100%発生するわけではありません.例えば、スレッドt 1が先にロックlock 1を起動して取得し、スリープ中のこの1 sの過程でJVMはスレッドスケジューリングが発生せず(実際にはほとんど不可能)、t 2が実行されずロックlock 2も取得されません.このときt 1がスリープ終了してロックlock 2が取得されると、この場合デッドロックは発生しない.100%デッドロックが発生するプログラムをどのように書きますか?直接コード:
public class DeadLockTest {    private static Object lock1 = new Object();    private static Object lock2 = new Object();    //    flag   volatile  ,          
    private static volatile boolean flag1 = false;    private static volatile boolean flag2 = false;    public static void main(String[] args) {        new Thread(() -> {
            synchronized (lock1) {
                flag1 = true;
                System.out.println("thread1 acquired lock1");                while (!flag2) {                    //     ,  thread2   lock2        (    Thread.sleep(1000)     100%     )
                    Thread.yield();
                }
                System.out.println("thread1 try to acquire lock2");
                synchronized (lock2) {
                    System.out.println("thread1 acquired lock2");
                }
            }
        }, "t1").start();        new Thread(() -> {
            synchronized (lock2) {
                flag2 = true;
                System.out.println("thread2 acquired lock2");                while (!flag1) {
                    Thread.yield();
                }
                System.out.println("thread2 try to acquire lock1");
                synchronized (lock1) {
                    System.out.println("thread2 acquired lock1");
                }
            }
        }, "t2").start();        //     
        checkDeadLock();
        System.out.println("main thread end");
    }    public static void checkDeadLock() {
        ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
        ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(1);        //     5 ,  10     
        scheduled.scheduleAtFixedRate(() -> {            long[] threadIds = mxBean.findDeadlockedThreads();            if (threadIds != null) {
                System.out.println("       :");
                ThreadInfo[] threadInfos = mxBean.getThreadInfo(threadIds);                for (ThreadInfo info : threadInfos) {
                    System.out.println(info.getThreadId() + ":" + info.getThreadName());
                }
            }
        }, 5L, 10L, TimeUnit.SECONDS);
    }
}