死锁(二十四)

死锁(二十四)

什么是死锁

死锁指的是两个线程分别获取对方手上的资源,导致两个线程都阻塞,程序卡死的情况。就好比有两个玩具,两个小孩人手一个,这时两个小孩都想要对方手上的玩具;当然,作为人我们可以相互交换,但是计算器没有这么聪明,就相互卡死了。

package com.unsafe;

public class DeathLock {
    public static void main(String[] args) {
        Kid kid1 = new Kid("小明", 1);
        Kid kid2 = new Kid("小红", 0);
        new Thread(kid1).start();
        new Thread(kid2).start();
    }
}

class Flight {}

class Train {}

class Kid implements Runnable{
    static final Flight flight = new Flight();
    static final Train train = new Train();
    String name;
    int choice;

    public Kid(String name, int choice) {
        this.name = name;
        this.choice = choice;
    }

    @Override
    public void run() {
        if (choice==1) {
            synchronized (flight) {
                System.out.println(this.name+"拿到了flight");
                synchronized (train) {
                    System.out.println(this.name+"拿到了train");
                }
            }
        } else {
            synchronized (train) {
                System.out.println(this.name+"拿到了train");
                synchronized (flight) {
                    System.out.println(this.name+"拿到了flight");
                }
            }
        }
    }
}

我们可以看到,小明和小红两个小朋友,分别拿了飞机和火车的玩具,都想要拿对方手上的玩具,这时就造成了死锁,运行结果如下,程序就这么卡住,无法继续往下走了。

小明拿到了flight
小红拿到了train

产生死锁的必要条件

  1. 互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用。
  2. 请求和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放。
  3. 不剥夺条件:进程已获得的资源在未使用完之前,不能剥夺,只能在使用完时由自己释放。
  4. 环路等待条件:在发生死锁时,必然存在一个进程--资源的环形链。

避免死锁

避免死锁我们只需要打破上面四个条件中的一个即可,那么我们要怎样避免这种死锁的情况呢?上面的例子中,我们只要在获取对方的玩具的时候,先放下自己手上的玩具就行啦,看下面的代码。

package com.unsafe;

public class DeathLock {
    public static void main(String[] args) {
        Kid kid1 = new Kid("小明", 1);
        Kid kid2 = new Kid("小红", 0);
        new Thread(kid1).start();
        new Thread(kid2).start();
    }
}

class Flight {}

class Train {}

class Kid implements Runnable{
    static final Flight flight = new Flight();
    static final Train train = new Train();
    String name;
    int choice;

    public Kid(String name, int choice) {
        this.name = name;
        this.choice = choice;
    }

    @Override
    public void run() {
        if (choice==1) {
            synchronized (flight) {
                System.out.println(this.name+"拿到了flight");
            }
            synchronized (train) {
                System.out.println(this.name+"拿到了train");
            }
        } else {
            synchronized (train) {
                System.out.println(this.name+"拿到了train");
            }
            synchronized (flight) {
                System.out.println(this.name+"拿到了flight");
            }
        }
    }
}

这次我们来看结果,可以这场运行啦

小明拿到了flight
小红拿到了train
小红拿到了flight
小明拿到了train

Process finished with exit code 0
posted @ 2021-03-04 17:55  LucaZ  阅读(24)  评论(0编辑  收藏  举报