首先明确一点Java是无法从死锁状态中恢复的.
(1)线程锁死的条件:
a) 线程存在互斥
b) 至少有一个任务必须持有资源且正在等待获取一个当前被别的任务持有的资源
c) 资源不能被任务抢占,任务必须把资源释放当做普通事件.
d) 线程之间互相等待
(2)实例:
a) 一个单线程池,一个任务将另一个任务提交到同一个线程池中.并且等待另一个任务的结果,这就发生死锁.
b) A占有锁L,但是需要锁M,B占有锁M但是需要锁L,这就会发生锁死.
(3)避免锁死
a) 获得锁的请求都是顺序相同的,比如请求锁L和锁M都是,按照L到M的顺序.设计锁的顺序是并发程序设计的一部分.
b) 在使用嵌套的锁,嵌套synchronized块时,仔细考虑是否会发生两个及两个以上的块中的锁对象发生交换.比如synchronized(a){synchronized(b){}} a和b交换位置.这会使得发生请求锁的顺序不一致.可以使用对象的hash码(如果对象有唯一的性的域,也可以使用此域)作为比较标准,来安排a和b的位置,要顺序一致.
c) 设计并发程序时,获得锁的时候调用外部方法需要特殊谨慎,你要了解到你要调用的方法会持有哪个对象的锁..保持你的synchronized块/显示锁,仅仅是保护你方法内需要保护的共享数据就好.减少使用synchronized方法,使用synchronized块来保护较少的区域.
d) 如果一个程序一次获得一个锁,就不会产生死锁,不过这不靠谱= =.
e) 尝试使用Lock类加锁.
f) 不要改变线程的优先级.