写点什么

什么是死锁?它是如何产生的?

作者:javacn.site
  • 2023-06-06
    陕西
  • 本文字数:1641 字

    阅读完需:约 5 分钟

什么是死锁?它是如何产生的?

死锁(Dead Lock)指的是两个或两个以上的运算单元(进程、线程或协程),互相持有对方所需的资源,导致它们都无法向前推进,从而导致永久阻塞的问题就是死锁。


比如线程 1 拥有了锁 A 的情况下试图获取锁 B,而线程 2 又在拥有了锁 B 的情况下试图获取锁 A,这样双方就进入相互阻塞等待的情况,如下图所示:



死锁的代码实现如下:


public class DeadlockDemo {    public static void main(String[] args) {        Object lock1 = new Object();        Object lock2 = new Object();
Thread thread1 = new Thread(() -> { synchronized (lock1) { System.out.println("Thread 1 acquired lock1"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
synchronized (lock2) { System.out.println("Thread 1 acquired lock2"); } } });
Thread thread2 = new Thread(() -> { synchronized (lock2) { System.out.println("Thread 2 acquired lock2"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
synchronized (lock1) { System.out.println("Thread 2 acquired lock1"); } } });
thread1.start(); thread2.start(); }}
复制代码


在上面的示例中,我们创建了两个锁 lock1 和 lock2,并在两个线程中分别获取这两个锁,但是获取的顺序不同。当 thread1 获取 lock1 后,它会在持有锁 lock1 的情况下尝试获取 lock2,而当 thread2 获取 lock2 后,它会在持有锁 lock2 的情况下尝试获取 lock1。如果这两个线程启动后,thread1 先获取 lock1 并且在获取 lock2 之前休眠,那么 thread2 就会获取 lock2,然后在尝试获取 lock1 时被阻塞。此时,thread1 就会在获取 lock2 时被阻塞。两个线程都在等待对方释放锁,从而形成了死锁。

死锁 4 大条件

死锁的产生需要满足以下 4 个条件:


  1. 互斥条件:指运算单元(进程、线程或协程)对所分配到的资源具有排它性,也就是说在一段时间内某个锁资源只能被一个运算单元所占用。

  2. 请求和保持条件:指运算单元已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它运算单元占有,此时请求运算单元阻塞,但又对自己已获得的其它资源保持不放。

  3. 不可剥夺条件:指运算单元已获得的资源,在未使用完之前,不能被剥夺。

  4. 环路等待条件:指在发生死锁时,必然存在运算单元和资源的环形链,即运算单元正在等待另一个运算单元占用的资源,而对方又在等待自己占用的资源,从而造成环路等待的情况。


只有以上 4 个条件同时满足,才会造成死锁。

解决死锁

死锁的常用解决方案有以下两个:


  1. 按照顺序加锁:尝试让所有线程按照同一顺序获取锁,从而避免死锁。

  2. 设置获取锁的超时时间:尝试获取锁的线程在规定时间内没有获取到锁,就放弃获取锁,避免因为长时间等待锁而引起的死锁。

死锁排查工具

有一些工具可以帮助排查死锁问题,常见的工具有以下几个:


  1. jstack:可以查看 Java 应用程序的线程状态和调用堆栈,可用于发现死锁线程的状态。

  2. jconsole 和 JVisualVM:这些是 Java 自带的监视工具,可以用于监视线程、内存、CPU 使用率等信息,从而帮助排查死锁问题。

  3. Thread Dump Analyzer(TDA):是一个开源的线程转储分析器,可用于分析和诊断 Java 应用程序中的死锁问题。

  4. Eclipse TPTP:是一个开源的性能测试工具平台,其中包含了一个名为 Thread Profiler 的工具,可以用于跟踪线程运行时的信息,从而诊断死锁问题。


本文已收录至《Java 面试突击》,专注 Java 面试 100 年,查看更多:www.javacn.site

用户头像

javacn.site

关注

还未添加个人签名 2023-05-16 加入

还未添加个人简介

评论

发布
暂无评论
什么是死锁?它是如何产生的?_javacn.site_InfoQ写作社区