死锁和活锁

有大量同步策略可以解决数据竞争问题,其中最简单的就是锁。每一个要访问共享数据片的
任务在访问数据前必须申请得到锁,然后执行计算;最后要释放锁,以便其他任务可以对这
些数据执行别的操作。不幸的是,尽管锁在一定程度上能避免数据竞争,但是它也给现代软
件开发带来了严重问题。
最主要的问题是,锁不具有可组合性。我们不能保证由两部分以锁为基础、能正确运行的代
码合并得到的程序依然正确。而现代软件开发的基础恰恰是将小程序库合并为更大程序的组
装能力;因此,我们无法做到不考察组件的具体实现,就能在它们的基础上组装大软件。
造成组装失败的祸首是死锁。考虑最简单的情况,当两个任务以相反的顺序申请两个锁时,
死锁就出现了:线程T1 获得了锁L1,线程T2 获得了锁L2,然后,T1申请获得锁L2,同时
T2 申请获得L1。此时,两个线程将永久阻塞,死锁的情况就出现了。
死锁发生必须同时满足以下四个条件:
1. 互斥:至少有一个资源必须处于非共享模式;即一次只有一个线程使用。如果另一资源
申请该资源,那么申请线程必须延迟直到该资源释放为止。
2. 占有并等待:一个线程必须占有至少一个资源,并等待另一个资源,而该资源为其他线
程所占用。
3. 非抢占:资源申请者不能强行从资源占有着手中夺取资源,并且所有线程都不放弃已经
占有的资源。
4. 循环等待:有一组线程{T0,T1,…,Tn},T0等待的资源被T1 占用,T1等待的资源被T2
占用,Tn-1等待的资源被Tn占用。
只要破坏以上条件就可以避免死锁。
要避免死锁,最好的方法是复制原本需要互斥访问的资源,这样每一个线程都拥有一个资源
的私有副本。每个线程访问自己的副本,从而可以避免使用锁。如果有需要的话,可以在程
序的最后将各个线程占有的资源副本合并成一个单一的共享资源副本。这种不使用锁的方
法,从根本上消除了死锁存在的可能,并进一步提高了可扩展性和该组件的可组装性。
如果资源无法被复制,那么一般的做法是按照一定的顺序获取资源(锁),保存一致的锁获
取顺序可避免死锁环的出现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值