概念

什么是死锁?

  1. 个人理解:多个线程相互占据对方需要的资源,并且互相等待对方释放资源而僵持不下
  2. 多个线程各自占有一些公共资源,并且互相等待对方释放资源才能运行;
  3. 当某一个同步块同时拥有“两个以上对象的锁”时,就可能发生死锁问题,从而导致两个或多个线程都在等待对方释放资源,都停止的情况

产生死锁的四个必要条件

  1. 一个资源每次只能被一个线程使用(即多个线程竞争同一资源)
  2. 请求与保持条件:一个线程因请求资源而阻塞,对已经获得的资源保持不放
  3. 不剥夺条件:进程已获得的资源,在为使用完之前,不强行剥夺
  4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系

死锁的避免方法

  • 打破上述死锁的必要条件之中的任意一个或者多个条件

死锁示例

  1. 背景:灰姑娘和白雪公主两位?‍小仙女要化妆(拿着镜子涂口红),现有?、?一份
  2. 满足死锁的条件:
    • 两位小仙女竞争?、?(资源竞争)
    • 开始灰姑娘拿到?、白雪公主拿到?,然后两个小仙女等待拿到对方手里的资源(请求与保持)
    • 两位小仙女礼貌且文明,不去抢夺对方手里的资源(不剥夺)
    • 灰姑娘等待白雪公主手里的?,白雪公主等待灰姑娘手里的口红(循环等待)
public class DeadLock {
    public static void main(String[] args) {
        Girl g1=new Girl(0,"灰姑娘");
        Girl g2=new Girl(1,"白雪公主");
        //启动线程
        g1.start();
        g2.start();
    }
}
//口红
class Lipstick {

}
//镜子
class Mirror{

}
//?‍♀️
class Girl extends Thread{
    //需要的资源只有一份,用static来保证
    static Lipstick lipstick=new Lipstick();
    static Mirror mirror =new Mirror();

    int choice; //选择
    String girlName;    //小仙女的名字

    Girl(int choice, String girlName){
        this.choice=choice;
        this.girlName = girlName;
    }
    
    @Override
    public void run() {
        makeUp();
    }
    //化妆,互相持有对方的锁,即需要拿到对方的资源
    private void makeUp(){
        if(choice == 0){
            synchronized (lipstick) {   //拿到口红的锁
                System.out.println(this.girlName+"获得口红的锁");
                try {
                    Thread.sleep(1000); //睡眠1秒钟
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (mirror){  //一秒钟后想要获得镜子的锁
                    System.out.println(this.girlName + "获得镜子的锁");
                }
            }
        }
        else{
            synchronized (mirror) { //拿到镜子的锁
                System.out.println(this.girlName+"获得镜子的锁");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lipstick) {   //1秒钟后想获得口红的锁
                    System.out.println(this.girlName + "获得口红的锁");
                }
            }
        }
    }
}