什么是线程死锁?如何避免死锁?看一次就明白

认识线程死锁

线程死锁描述的是这样一种情况:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期的阻塞,因此程序不可能正常终止。

如下图所示,线程A持有资源2,线程B持有资源1,他们同时都想申请对方的资源,所以这两个线程就会互相等待而进入死锁状态。


下面通过一个例子来说明线程死锁,代码模拟了上面死锁的情况(代码来源于《并发编程之美》);


Output:


线程A通过synchronized(resource1)获得resource1的监视器锁,然后通过
Thread.sleep(1000);让线程A休眠1秒,为了是让线程B得到执行然后获取到resource2的监视器锁。线程A和线程B休眠结束了都开始企图请求获取对方的资源,然后这两个线程就会陷入互相等待的状态,这也就产生了死锁。上面的例子产生死锁的4个必要条件。

学过操作系统的朋友都知道产生死锁必须具备以下4个条件:

  1. 互斥条件:该资源任意一个时刻只由一个线程占用。
  2. 请求与保持条件:一个进程因为请求资源而阻塞时,对已获得的资源保存不放。
  3. 不剥夺条件:线程已获得的资源在未使用完之前不能被其他线程强制剥夺,只有之间使用完毕后才会释放资源。
  4. 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。

如何避免线程死锁?

我上面说了产生死锁的4个必要条件,为了避免死锁,我们只要破坏产生死锁的4个条件中的1个就可以了,我们现在来挨个分析一下:

  1. 破坏互斥条件:这个条件我们没有办法破坏,因为我们用锁本来就是想让它们互斥的(临界资源需要互斥访问)。
  2. 破坏请求与保持条件:一次性申请所有资源。
  3. 破坏不剥夺条件:占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源
  4. 破坏循环等待条件:按某一个顺序来申请资源,释放资源则反序释放。破坏循环等待条件

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


Output:


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

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

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值