• 6.18Java死锁的产生与解决


    6.18Java死锁的产生与解决

    死锁的简单描述

    简单说就是在一个同步块中同时持有两个对象的锁

    系统描述:

    • 多个线程各自占有一些共享资源

    • 互相等待其他线程占有的资源

    满足以上两点就会导致两个或者多个线程都在等待对方释放资源,都停止执行的情况。

    某一个同步块同时拥有"两个以上对象的锁"时,就会发生死锁问题--->过多的同步可能会造成死锁

    实例demo

    package iostudy.synchro;

    /**
    * 死锁:过多的同步导致线程相互不释放共享资源
    * 从而相互等待。一般发生于同步中持有多个对象的锁
    * @since JDK 1.8
    * @date 2021/6/18
    * @author Lucifer
    */
    public class DeadLock {
       public static void main(String[] args) {

           /*创建两个线程*/
           Markup markup1 = new Markup(1, "Lucifer");
           Markup markup2 = new Markup(2, "James");

           markup1.start();
           markup2.start();
      }
    }

    /**
    * 创建一个口红类
    */
    class Lipstick{

    }

    /**
    * 创建一个镜子类
    */
    class Mirror{

    }

    /**
    * 一个线程类--->化妆
    */
    class Markup extends Thread{

       /*静态资源类对象*/
       static Lipstick lipstick = new Lipstick(); //静态的无论创建几个对象都是一份属性
       static Mirror mirror = new Mirror();

       /*选择镜子还是口红--->0是镜子,1是口红*/
       int choice;

       /*名字*/
       String girl;

       /*构造器*/
       public Markup(int choice, String girl){
           this.choice = choice;
           this.girl = girl;
      }

       /*重写Thread类下的run方法*/
       @Override
       public void run(){
           //化妆的方法--->在下面写具体的实现
           markup();
      }

       /*相互持有对方的对象锁的方法--->才可能造成死锁*/
       private void markup(){
           if (choice==0){
               /*获得口红的锁*/
               synchronized (lipstick){
                   System.out.println(this.girl + "获得口红!");

                   /*一秒后拥有镜子*/
                   try {
                       Thread.sleep(1000);
                  }catch (InterruptedException e){
                       System.out.println(e.getMessage());
                       e.printStackTrace();
                  }

                   /*相互持有对象锁,所以在加一个syn*/
                   synchronized (mirror){
                       System.out.println(this.girl + "拿镜子!");
                  }
              }
          }else {
               /*获得镜子的锁*/
               synchronized (mirror){
                   System.out.println(this.girl + "拿镜子!");

                   /*两秒后拥有口红的锁--->故意形成时间间隔才有可能造成相互不释放资源*/
                   try {
                       Thread.sleep(2000);
                  }catch (InterruptedException e){
                       System.out.println(e.getMessage());
                       e.printStackTrace();
                  }

                   /*相互持有对象锁,所以在加一个syn*/
                   synchronized (lipstick){
                       System.out.println(this.girl + "获得口红!");
                  }
              }
          }
      }
    }
    分析
    • 当choice为0,先拿lipstick锁才能往下执行

    • 1s后,需要先拿mirror锁才能继续执行

    • choice为1的时候,先拿mirror锁才能往下执行

    • 2s后,需要拿lipstick的锁才能往下执行

    在方法中相互不释放,相互持有对方的资源,导致死锁

    死锁的解决--->保证不要相互持有对方的锁

    因为同步块都持有了两个属性的锁,所以要改挪动一下代码即可--->不要锁套锁

    package iostudy.synchro;

    /**
    * 死锁:过多的同步导致线程相互不释放共享资源
    * 从而相互等待。一般发生于同步中持有多个对象的锁
    *
    * 避免方法:
    * 不要再同一个代码块当中同时持有多个对象的锁
    * @since JDK 1.8
    * @date 2021/6/18
    * @author Lucifer
    */
    public class DeadLock {
       public static void main(String[] args) {

           /*创建两个线程*/
           Markup markup1 = new Markup(1, "Lucifer");
           Markup markup2 = new Markup(2, "James");

           markup1.start();
           markup2.start();
      }
    }

    /**
    * 创建一个口红类
    */
    class Lipstick{

    }

    /**
    * 创建一个镜子类
    */
    class Mirror{

    }

    /**
    * 一个线程类--->化妆
    */
    class Markup extends Thread{

       /*静态资源类对象*/
       static Lipstick lipstick = new Lipstick(); //静态的无论创建几个对象都是一份属性
       static Mirror mirror = new Mirror();

       /*选择镜子还是口红--->0是镜子,1是口红*/
       int choice;

       /*名字*/
       String girl;

       /*构造器*/
       public Markup(int choice, String girl){
           this.choice = choice;
           this.girl = girl;
      }

       /*重写Thread类下的run方法*/
       @Override
       public void run(){
           //化妆的方法--->在下面写具体的实现
           markup();
      }

       /*相互持有对方的对象锁的方法--->才可能造成死锁*/
       private void markup(){
           if (choice==0){
               /*获得口红的锁*/
               synchronized (lipstick){
                   System.out.println(this.girl + "获得口红!");

                   /*一秒后拥有镜子*/
                   try {
                       Thread.sleep(1000);
                  }catch (InterruptedException e){
                       System.out.println(e.getMessage());
                       e.printStackTrace();
                  }
              }

               /*相互持有对象锁,所以在加一个syn*/
               synchronized (mirror){
                   System.out.println(this.girl + "拿镜子!");
              }

          }else {
               /*获得镜子的锁*/
               synchronized (mirror){
                   System.out.println(this.girl + "拿镜子!");

                   /*两秒后拥有口红的锁--->故意形成时间间隔才有可能造成相互不释放资源*/
                   try {
                       Thread.sleep(2000);
                  }catch (InterruptedException e){
                       System.out.println(e.getMessage());
                       e.printStackTrace();
                  }
              }

               /*相互持有对象锁,所以在加一个syn*/
               synchronized (lipstick){
                   System.out.println(this.girl + "获得口红!");
              }

          }
      }
    }

     

     

    It's a lonely road!!!
  • 相关阅读:
    ORACLE 计算时间相减间隔
    oracle中游标详细用法
    oracle中计算某月的天数
    Unity3D导出的EXE不用显示分辨率选择界面
    Unity3D 之暂停和继续的实现
    double的值太大,以及补0
    Unity3D鼠标点击物体产生事件
    java POi excel 写入大批量数据
    Unity3D 判断鼠标是否按在UGUI上
    Unity3D 之UGUI 滚动条
  • 原文地址:https://www.cnblogs.com/JunkingBoy/p/14901009.html
Copyright © 2020-2023  润新知