死锁的实现与检测

这是一道经典的面试题。今天的内容就是手动编写一个死锁代码,然后简要分析一下这个死锁代码。

在讲正文前,先讲下 jdk 11 的一个新特性,可以直接运行单个的 Java 文件。而不用 javac 编译成 class,再运行。下文图中就是例子:

java OddEvenPrinter.java 

以后写 Demo 就不用非得用 ide 了,直接用记事本也是可以的跟 python 玩法就一样了。

回归正文,锁存在的目的就是在多线程竞争时,保证同时只有一个线程能获取锁执行代码,其余线程等待,保证线程安全的方式。(好像说的稀碎)

而死锁,就是两个或者多个线程互相持有别的线程需要的锁,而且都不主动释放的状态,我记得教科书上有死锁存在的必要条件:

(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 占有且等待:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3)不可强行占有:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

我的描述基本就是上面四句话的意思。所以造一个最简单的死锁例子就是用两个线程,定义两个对象,并且线程1持有 monitorA 然后申请 monitorB,线程2持有 monitorB 然后申请 monitorA。

public class Lock {

    private final Object monitorA = new Object();
    private final Object monitorB = new Object();

    public void printA() {
        synchronized (monitorA) {
            try {
                // 暂停一下,让线程2有时间先获取 monitorB 的锁,否则线程1可能会直接执行完成
                Thread.sleep(10);
            } catch (Exception e) {
                //TODO: handle exception
            }
            synchronized (monitorB) {
                System.out.println("printA");
            }
        }
    }

    public void printB() {
        synchronized (monitorB) {
            synchronized (monitorA) {
                System.out.println("printB");
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Lock printer = new Lock();
        Thread thread1 = new Thread(printer::printA, "thread-1");
        Thread thread2 = new Thread(printer::printB, "thread-2");
        thread1.start();
        thread2.start();
    }
}

代码中线程1在 synchronized (monitorA) 的里面添加了睡眠语句,这是为了等待线程 2 去执行完 synchronized (monitorB) 否则会导致线程 A 直接申请了 synchronized (monitorB) 两个线程就变成串行化执行了。

这是简单例子,运行时会发现命令行什么都不输出,我们可以打印输出,看看停在了哪里,但是如果是生产环境发生死锁,我们没有条件知道到底哪里死锁,也基本不能尝试添加大量 log。那么如何检测死锁以及死锁的原因呢?祭出大杀器:JConsole

在命令行输入 jconsole,然后选择需要监听哪个进程,这个如何确定哪个进程是你的,就算做课外作业了:)。

线程 -> 检测死锁,可以看到,thread-1 和 thread-2发生死锁,thread-1 的并且在 Lock.java 14行,被锁住。

image.png

14行代码是什么呢?

也就是可以看到 monitorB,这也符合我们的本意,因为它已经被 thread-2 给占用了。

当生产环境发生了死锁时,我们也可以通过此方法检测死锁问题。

by 费城的二鹏 2020.07.24 长春

你可能感兴趣的:(死锁的实现与检测)