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 + "获得口红!");
          }

      }
  }
}

 

 

posted @ 2021-06-18 19:38  俊king  阅读(144)  评论(0编辑  收藏  举报