page contents

@$如何避免线程死锁?

轩辕小不懂 发布于 2022-08-06 11:16
阅读 20
收藏 0
分类:高并发
4020
Nen
Nen
- 程序员

我们只要破坏产生死锁的四个条件中的其中一个就可以了。

破坏互斥条件

这个条件我们没有办法破坏,因为我们用锁本来就是想让他们互斥的(临界资源需要互斥访问)。

破坏请求与保持条件

一次性申请所有的资源,会降低并发能力,一般不破坏请求与保持条件。

破坏不剥夺条件

占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。

破坏循环等待条件

靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。

我们对线程 2 的代码修改成下面这样就不会产生死锁了。

new Thread(() -> {

   synchronized (resource1) {

       System.out.println(Thread.currentThread() + "get resource1");

       try {

           Thread.sleep(1000);

      } catch (InterruptedException e) {

           e.printStackTrace();

      }

       System.out.println(Thread.currentThread() + "waiting get resource2");

       synchronized (resource2) {

           System.out.println(Thread.currentThread() + "get resource2");

      }

  }

}, "线程 2").start();

输出结果

Thread[线程 1,5,main]get resource1

Thread[线程 1,5,main]waiting get resource2

Thread[线程 1,5,main]get resource2

Thread[线程 2,5,main]get resource1

Thread[线程 2,5,main]waiting get resource2

Thread[线程 2,5,main]get resource2

我们分析一下上面的代码为什么避免了死锁的发生?

线程 1 首先获得到 resource1 的监视器锁,这时候线程 2 就获取不到了。然后线程 1 再去获取 resource2 的监视器锁,可以获取到。然后线程 1 释放了对 resource1、resource2 的监视器锁的占用,线程 2 获取到就可以执行了。这样就破坏了破坏循环等待条件,因此避免了死锁。

请先 登录 后评论