死锁问题与解决方式

什么是死锁

·死锁的含义:

死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外界干涉,那它们都将无法继续推进下去。如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就会很低,否则就会因争夺有限的资源而陷入死锁状态。如下:
在这里插入图片描述

·产生死锁的原因:

  1. 系统资源不足
  2. 进程运行推进的顺序不合适
  3. 资源分配不当

·产生死锁的必要条件:

只有当这四个条件同时满足时,死锁才会发生。

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();


    }
}

解决死锁:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值