死锁的形成与解决方法

在多线程编程中我们常常需要通过加锁来保证线程的安全,但是如果我们操作不当就可能会出现死锁的情况,接下来我们就来介绍死锁。

#死锁的形成

首先了解以下什么是死锁,死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线 程被无限期地阻塞,因此程序不可能正常终止。简单来说就是有两个线程一个为线程1持有A锁一个为线程2持有B锁,此时线程1的结束依赖以B锁,线程2的结束依赖以A锁,也就是说此时两个线程互不相让,都不让出自己所持有的锁从而导致了死锁。针对线程的死锁有一个著名的问题,哲学家吃面问题。

我们假设餐桌上有5个哲学家,5把筷子,这些哲学家只会做两件事就是吃面或者思考。当哲学家吃面时就需要拿起两把筷子,当然相邻的2个哲学家中如果有一人先拿到两把筷子那么另一个人在拿到一把筷子后就需要等待其放下一把筷子

 此时B就要等待A使用完2号筷子才能吃面,这就好比B是进入了阻塞队列的线程。接下来我们来讨论一个极端的情况,那就是5个哲学家同时拿起了他们左手边的筷子

此时每个哲学家都在等待拿到右手边的筷子 ,但是显而易见每个哲学家没吃面都在思考(阻塞)这样就永远都吃不到面,这也就是一种N个线程对应N把锁可能产生的死锁问题。

#解决死锁的方法

了解了死锁后我们就可以考虑如何来解决了,其实死锁的产生有四个必要条件

1.互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用

2.不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。

3.请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。

4.循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样 就形成了一个等待环路。

当上述四个条件都成立的时候,便形成死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让 死锁消失。虽然我们只要破坏其中的一个条件即可,但是我们在日常编程中还是破坏第四个条件比较容易,所以我们解决死锁的思路就是破坏他们的循环等待。我们上文提到的哲学家问题中,5个哲学家分别在等待其他人放下筷子如果我们能够打断这种循环等待那么也就解决了死锁的问题。要解决这个问题我们就要针对哲学家怎么拿筷子这个问题进行讨论,如果哲学家每次都随机的先拿起左边或者右边的筷子就极大可能对旁边的哲学家造成影响。如此我们来做一个规定,每个哲学家必须先拿到其能拿到的筷子中序号较小的

 

 此时则E不会拿起5号筷子,那么D拿起4号筷子就可以拿到5号筷子当D吃完面后就会放下两把筷子,之后C就能拿到4号筷子以此类推当A放下1号筷子时E也就可以开始吃面了,这样就解决了线死锁,也就是说我们只要给每把锁做记号在约定规则就能打破循环等待从而解决死锁。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值