死锁是指多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。例如,在某一个计算机系统中只有一台打印机和一台输入 设备,进程P1正占用输入设备,同时又提出使用打印机的请求,但此时打印机正被进程P2 所占用,而P2在未释放打印机之前,又提出请求使用正被P1占用着的输入设备。这样两个进程相互无休止地等待下去,均无法继续执行,此时两个进程陷入死锁状态。
1.区别死锁,饥饿,死循环
死锁:并发情况下,所有进程进入阻塞,而无法处理;
饥饿:迟迟等不到资源分配;
死循环:某个进程陷入循环跳不出来。
2.死锁产生的四个条件,缺一不可
1.互斥条件
2.不剥夺条件
3.请求和保持条件
4.循环等待条件
3.什么时候回发生死锁?
1.对资源的竞争:系统资源的竞争导致系统资源不足,以及资源分配不当,导致死锁。
2.进程顺序非法:进程在运行过程中,请求和释放资源的顺序不当,会导致死锁;
3.信号量使用不当
4.如何预防死锁?
破坏四个必要条件里的一个
(1)破坏互斥:SPOOLING技术(排队)
(2)破坏剥夺:自己放弃自己要得资源、强行抢夺自己要的资源;第二种是动态分配即每个进程在申请所需要的资源时他本身不占用系统资源。
(3)破坏请求保持条件:静态分配资源,如果得到该进程想要的全部资源就不运行
(4)破坏循环等待条件:顺序资源分配法:采用资源有序分配其基本思想是将系统中的所有资源顺序编号,将紧缺的,稀少的采用较大的编号,在申请资源时必须按照编号的顺序进行,一个进程只有获得较小编号的进程才能申请较大编号的进程。
5.如何避免死锁?
安全序列:如果系统存在由所有的安全序列{P1,P2,…Pn},则系统处于安全状态。一个进程序列是安全的,如果对其中每一个进程Pi(i >=1 && i <= n)他以后尚需要的资源不超过系统当前剩余资源量与所有进程Pj(j < i)当前占有资源量之和,系统处于安全状态则不会发生死锁。
6.死锁的检测和免除
为了能对系统是否死锁进行检测
(1)用某种数据结构来保存资源的请求和分配信息
(2)提供一种算法,根据上述信息来检测系统是否死锁
请求边
进程节点=======资源节点
分配边
检查最后是不是所有进程节点都是孤立节点
解除死锁的主要方法
1.资源剥夺法 2.撤销进程法 3.进程回退法
死锁代码:
public class DeadLock { public static void main(String[] args) { DeadLockThread deadLock1=new DeadLockThread(true); DeadLockThread deadLock2=new DeadLockThread(false); Thread t1=new Thread(deadLock1); Thread t2=new Thread(deadLock2); t1.start(); t2.start(); } } class DeadLockThread implements Runnable{ boolean flag; static Object o1=new Object();//这里必须是静态变量,否则加锁就不是在同一个对象上加锁了 static Object o2=new Object(); public DeadLockThread(boolean flag){ this.flag=flag; } public void run() { if(flag){ synchronized(o1){ try{ Thread.sleep(100); } catch(InterruptedException e){ e.printStackTrace(); } synchronized(o2){//要放在o1临界区内,因为要保持o1的锁,申请o2的锁 System.out.println("I am not dead lock!"); } } } else{ synchronized(o2){ try{ Thread.sleep(100); } catch(InterruptedException e){ e.printStackTrace(); } synchronized(o1){//此处类似,保持o2的锁,申请o1的锁 System.out.println("I am not dead lock, too."); } } } } }