什么是死锁
·死锁的含义:
死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外界干涉,那它们都将无法继续推进下去。如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就会很低,否则就会因争夺有限的资源而陷入死锁状态。如下:
·产生死锁的原因:
- 系统资源不足
- 进程运行推进的顺序不合适
- 资源分配不当
·产生死锁的必要条件:
只有当这四个条件同时满足时,死锁才会发生。
1、资源不可剥夺:
资源不能被强占剥夺,只能被占有它的进程主动释放。
2、互斥访问:
独占资源只能分配给一个进程。其他进程需要使用时,只能等待资源由占用状态变成空闲状态。
3、请求且持有:
进程因为请求新的资源受阻,但不能释放已经占有的资源。
4、环路等待:
至少有两个及以上的进程形成一条环路,环路上的某一个进程请求的资源正是下一个进程所占有的资源。
代码演示:哲学家就餐问题
定义一个筷子类:
/**
* 这是一根筷子
*/
public class Chopstick {
private String num;//筷子编号
public Chopstick(String num) {
this.num = num;
}
public String getNum() {
return num;
}
}
定义哲学家类:
/**
* 这是一个可以 并发执行 的 哲学家线程。
* 由于每个哲学家线程都必须要得到两个资源之后,才会把得到的所有资源一个一个的释放掉。
* 所以,会出现一种死循环状态,产生死锁现象。
*/
public class Philosopher extends Thread{
private String name;
private Chopstick left; //左边的筷子
private Chopstick right;//右边的筷子
//构造方法
public Philosopher(String name,Chopstick left,Chopstick right){
this.name = name;
this.left = left;
this.right = right;
}
@Override
public void run() {
//首先 想要获得左边的筷子
synchronized (left){
System.out.println("\n"+this.name+" 拿起了左手边的 "+this.left.getNum()+" 筷子。");
//并且 还想获得右边的筷子
synchronized (right){
System.out.println(this.name+" 拿起了右手边的 "+this.right.getNum()+" 筷子。");
System.out.println(this.name+" 获得了两根筷子,开始吃了起来。");
}
//释放了,右边的筷子
System.out.println(this.name+" 放下了右手边的 "+this.right.getNum()+" 筷子。");
}
//释放了,左边的筷子
System.out.println(this.name+" 放下了左手边的 "+this.left.getNum()+" 筷子。");
}
}
可能会产生死锁的测试类:
/**
* 可能会产生死锁
*/
public class TestMain {
public static void main(String[] args) {
Chopstick c1 = new Chopstick("1号");
Chopstick c2 = new Chopstick("2号");
Chopstick c3 = new Chopstick("3号");
Chopstick c4 = new Chopstick("4号");
Philosopher p1 = new Philosopher("哲学家a",c2,c1);
Philosopher p2 = new Philosopher("哲学家b",c3,c2);
Philosopher p3 = new Philosopher("哲学家c",c4,c3);
Philosopher p4 = new Philosopher("哲学家d",c1,c4);
p1.start();
p2.start();
p3.start();
p4.start();
}
}
产生死锁:
解决死锁问题:
/**
* 可以解决死锁问题
*/
public class TestMain {
public static void main(String[] args) {
Chopstick c1 = new Chopstick("1号");
Chopstick c2 = new Chopstick("2号");
Chopstick c3 = new Chopstick("3号");
Chopstick c4 = new Chopstick("4号");
//让哲学家a和c先吃,b和d后吃。
Philosopher p1 = new Philosopher("哲学家a",c2,c1,0);
Philosopher p2 = new Philosopher("哲学家b",c3,c2,1000);
Philosopher p3 = new Philosopher("哲学家c",c4,c3,0);
Philosopher p4 = new Philosopher("哲学家d",c1,c4,1000);
p1.start();
p2.start();
p3.start();
p4.start();
}
}
解决死锁: