zoukankan      html  css  js  c++  java
  • 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!!!
  • 相关阅读:
    JAVA基础补漏--文件读取
    JAVA-Lambda表达式
    JAVA基础补漏--可变参数
    JAVA基础补漏--SET
    Apache ab 测试结果的分析
    同源策略和跨域问题
    php curl 伪造IP来源的实例代码
    HTTP状态码详解
    PHP 根据IP地址获取所在城市
    MySQL MERGE存储引擎 简介及用法
  • 原文地址:https://www.cnblogs.com/JunkingBoy/p/14901009.html
Copyright © 2011-2022 走看看