产生死锁的原因:
1. 系统资源不足、分配不当。系统中都会有一种不可剥夺的资源,若是这些资源不能够满足进程运行的需要,那么就只能进行资源争夺,从而陷入死锁。
注意:只有对不可剥夺资源的竞争才可能产生死锁,对可剥夺资源的竞争是不会引起死锁的。
2. 进程运行推进的顺序不合理。进程运行过程中,请求和释放资源的顺序不当,也可能产生死锁。
以两个线程为例,第一个线程A锁住了一个资源1,另一个线程B也同时锁住了另一个资源2,这时,第一个线程A经过一段时间操作,需要资源2来继续执行,但是资源2被线程B锁定,不能为线程A所用。同样,线程B经过一段时间操作,需要资源1来继续执行,但是资源1被线程A锁定,不能为线程B所用。这样就形成了资源互锁,出现了死锁状态。
死锁解决方法:
1. 线程按照一定的顺序加锁,避免嵌套封锁。当多个线程需要相同的一些锁,但是按照不同的顺序加锁,死锁就很容易发生。如果能确保所有的线程都是按照相同的顺序获得锁,那么死锁就不会发生。如果你已经有一个资源了就要避免封锁另一个资源。如果你运行时只有一个对象封锁,那是几乎不可能出现一个死锁局面的。
2. 加锁时限,避免无限期等待。既然死锁的产生是两个线程无限等待对方持有的锁,那么只要等待时间有个上限不就好了。尝试获取锁的时候加一个超时时间,这也就意味着在尝试获取锁的过程中若超过了这个时限该线程则放弃对该锁请求。若一个线程没有在给定的时限内成功获得所有需要的锁,则会进行回退并释放所有已经获得的锁,然后等待一段随机的时间再重试。这段随机的等待时间让其它线程有机会尝试获取相同的这些锁,并且让该应用在没有获得锁的时候可以继续运行。
3. 死锁检测,死锁检测是一个更好的死锁预防机制,它主要是针对那些不可能实现按序加锁并且锁超时也不可行的场景。每当一个线程获得了锁,会在线程和锁相关的数据结构中将其记下。除此之外,每当有线程请求锁,也需要记录在这个数据结构中。当一个线程请求锁失败时,这个线程可以遍历锁的关系图看看是否有死锁发生。