
多线程可提高系统资源的利用率并增加系统的处理能力. 但是,并发执行还会带来新的问题僵局. 所谓的死锁是由于资源竞争而在多个线程之间等待的一种方式. 如果没有外力,这些线程将无法继续执行.
系统中通常拥有的不可分割资源的数量不足以满足运行多个线程的需求,因此在运行过程中,线程将因争夺资源而陷入僵局线程死锁,例如磁带驱动器和打印机. 只有对不可剥夺资源的竞争才能导致僵局,而对不可剥夺资源的竞争也不会导致僵局.
在运行过程中,请求和释放资源的顺序不正确,这也将导致死锁. 例如,并发线程P1和P2分别维护资源R1和R2,并且当线程P1申请资源R2和线程P2申请资源R1时,两者都将阻塞,因为所需的资源已被占用.
不正确使用信号量也会导致死锁. 线程彼此等待,以相互发送消息. 结果,这些线程无法继续前进. 例如,线程A正在等待来自线程B的消息,线程B正在等待来自线程A的消息. 可以看出,线程A和B并未等待彼此的资源导致死锁.

死锁必须同时满足以下四个条件. 只要不满足任何一种条件,就不会发生死锁.
互斥条件: 线程需要对分配的资源(例如打印机)进行独占控制,也就是说,某个资源在一段时间内仅被一个线程占用. 此时,如果另一个线程请求资源,则请求线程只能等待非剥夺条件: 该线程获得的资源在用完之前不能被其他线程强行带走,也就是说线程死锁,它只能由获得资源的线程获得. 释放(只能被主动释放)请求和保持条件: 线程已保留至少一个资源,但发出了新的资源请求,并且该资源已被另一个线程占用. 这时,请求线程已被阻止,但它本身已被阻止. 获得的资源保持循环等待条件: 有一个循环等待的线程资源链,该链中的下一个线程同时请求该链中每个线程获取的资源. 也就是说,存在一组处于等待状态的线程{P1,P2,...,pn},其中Pi等待由P(i + 1)占用的资源(i = 0、1,..., n-1),等待资源的Pn被P0占用
在某些情况下可以避免死锁. 避免死锁的三种技术:
锁定顺序锁定时间死锁检测

当多个线程需要相同的锁,但是锁以不同顺序添加时,容易发生死锁.
顺序锁定是一种有效的防止死锁的机制. 但是,此方法需要事先知道所有可能使用的锁,但是有时这是不可预测的.
当线程在尝试获取锁时超过了此时间限制时,该线程应放弃请求该锁.
如果线程在给定的时间内未成功获取所有必需的锁,它将回滚并释放所有获取的锁,然后等待随机时间,然后重试. 这种随机的等待时间使其他线程有机会尝试获取相同的锁,并允许应用程序继续运行而无需获取锁.

应该注意的是,由于锁定超时,我们不能认为这种情况一定是死锁. 这也可能是因为获得锁的线程(导致其他线程超时)需要很长时间才能完成其任务.
此外,如果有很多线程在同一时间争夺同一批资源,即使存在超时和回滚机制,这些线程也可能会反复尝试但永远不会获得锁. 如果只有两个线程,并且将重试超时设置为0到500毫秒,则可能不会发生此现象,但是10或20个线程的情况有所不同. 因为这些线程更有可能等待相等的重试时间(或由于等待时间太短而导致问题).
死锁检测是一种更好的防止死锁的机制. 主要针对无法实现顺序锁定且锁定超时不可行的方案.
只要线程获得锁,它就会记录在与线程和锁相关的数据结构(映射,图形等)中. 此外,每当线程请求锁定时,都需要将其记录在此数据结构中.

当线程无法请求锁时,该线程可以遍历锁的关系图以查看是否发生了死锁.
那么当检测到死锁时这些线程应该怎么做?
一种可能的方法是释放所有锁,回滚并等待随机的时间段再尝试. 这类似于简单的锁定超时. 区别在于仅发生了死锁并将其回滚,而不是因为锁定请求已超时. 尽管存在回滚和等待,但是如果有大量线程在争用同一批锁,它们仍将反复死锁(编者注: 原因类似于超时,因此无法从根本上减少竞争).
一种更好的解决方案是为这些线程设置优先级,并让一个(或几个)线程回滚,而其余线程则继续持有所需的锁,就好像没有死锁一样. 如果赋予这些线程的优先级是固定的,则同一批线程将始终具有更高的优先级. 为避免此问题,可以在发生死锁时设置随机优先级.
Linux公社的RSS地址:
此链接已永久更新:
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-146222-1.html
好你们继续掐再给中国十年发展时间
#杨洋icon##杨洋2015金投赏#杨洋金投赏
你真的是不要脸