1.定义:所谓死锁: 是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
官方定义:死锁的规范定义:集合中的每一个进程都在等待只能由本集合中的其他进程才能引发的事件,那么该组进程是死锁的。
2.产生死锁的原因主要是:
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则
就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
3.产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之
一不满足,就不会发生死锁。
4.死锁的解除与预防:
理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和
解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确
定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态
的情况下占用资源。因此,对资源的分配要给予合理的规划。
具体方法:
只要打破四个必要条件之一就能有效预防死锁的发生:打破互斥条件:改造独占性资源为虚拟资源,大部分资源已无法改造。打破不可抢占条件:当一进程占有一独占性资源后又申请一独占性资源而无法满足,则退出原占有的资源。打破占有且申请条件:采用资源预先分配策略,即进程运行前申请全部资源,满足则运行,不然就等待,这样就不会占有且申请。打破循环等待条件:实现资源有序分配策略,对所有设备实现分类编号,所有进程只能采用按序号递增的形式申请资源
有序资源分配法
银行家算法
public class deadLock implements Runnable {
private int flag;
static Object o1 = new Object(), o2 = new Object(); // 静态的对象
public void run() {
System.out.println(flag);
if (flag == 0) {
synchronized (o1) {
try {所以在thread0线程启动的时候执行的是run()方法前半部分的代码,
Thread.sleep(500);
System.out.println(Thread.currentThread().getName()+"在执行");
} catch (Exception e) {
e.printStackTrace();
}
synchronized (o2) {//此时,出现了下列现象:thread1线程占有了o1对象并等待o2对象,
}
}
}
if (flag == 1) {//所以在thread0线程执行的时候执行的是执行此run()方法,flag等于1,
synchronized (o2) {//而thread1线程占有了o2对象并等待o1对象,而o1和o2又被这俩个线程所共享,所以就出现了死锁的问题了。
try {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName()+"在执行");
} catch (Exception e) {
e.printStackTrace();
}
synchronized (o1) {
}
}
}
}
public static void main(String[] args) {
deadLock test1 = new deadLock();//在main方法中,实例化了两个实现了Runnable接口的deadLock对象test1和test2,test1的flag等于1,
deadLock test2 = new deadLock();
test1.flag = 1;
test2.flag = 0;
Thread thread1 = new Thread(test1);
Thread thread2 = new Thread(test2);
thread1.start();
thread2.start();
}
}
0
1
Thread-1在执行
Thread-0在执行