• Java基础复习 Day 20


    Java基础复习 Day 20

    多线程(3)

    1. 多线程出现安全问题

      当多线程访问(有写操作,更改共享数据的值的时候)共享数据的时候,会产生线程安全问题

      以卖票案例为例做代码实现:(三个窗口同时卖100张1-100号的票,就会出现安全问题,同一张票可能会被卖多次,或者出现没有票了却还在被卖。。)

    //创建Runnable接口的实现类,定义共享数据
    /*
    * 实现卖票案例
    * */
    public class RunnableImpl implements Runnable{
        private int ticket = 100;
        @Override
        public void run() {
            while (true){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (ticket>0) {
                    System.out.println(Thread.currentThread().getName()+" 正在卖第: "+ ticket +"张票");
                    ticket--;
                }
            }
        }
    }
    //定义三个线程去访问这个共享数据
    /*
    * 创建三个线程让这三个线程都对共享的票进行出售
    * 共享体现在只有一个runnable的实现类,但是用三个线程来执行
    * */
    public class DemoMain {
        public static void main(String[] args) {
            RunnableImpl run = new RunnableImpl();
            Thread t1 = new Thread(run);
            Thread t2 = new Thread(run);
            Thread t3 = new Thread(run);
            t1.start();
            t2.start();
            t3.start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    打印结果

    Thread-2 正在卖第: 100张票
    Thread-0 正在卖第: 100张票
    Thread-1 正在卖第: 100张票
    Thread-1 正在卖第: 97张票
    Thread-0 正在卖第: 97张票
    Thread-2 正在卖第: 97张票
    Thread-2 正在卖第: 94张票
    Thread-1 正在卖第: 94张票
    Thread-0 正在卖第: 94张票
    Thread-0 正在卖第: 91张票
    Thread-2 正在卖第: 91张票
    Thread-1 正在卖第: 91张票
    Thread-1 正在卖第: 88张票
    Thread-2 正在卖第: 88张票
    Thread-0 正在卖第: 88张票
    Thread-2 正在卖第: 85张票
    Thread-0 正在卖第: 85张票
    Thread-1 正在卖第: 85张票
    Thread-1 正在卖第: 82张票
    Thread-2 正在卖第: 82张票
    Thread-0 正在卖第: 82张票
    Thread-2 正在卖第: 79张票
    Thread-1 正在卖第: 79张票
    Thread-0 正在卖第: 79张票
    Thread-1 正在卖第: 76张票
    Thread-0 正在卖第: 76张票
    Thread-2 正在卖第: 76张票
    Thread-2 正在卖第: 73张票
    Thread-0 正在卖第: 73张票
    Thread-1 正在卖第: 73张票
    Thread-2 正在卖第: 70张票
    Thread-0 正在卖第: 70张票
    Thread-1 正在卖第: 70张票
    Thread-1 正在卖第: 67张票
    Thread-0 正在卖第: 67张票
    Thread-2 正在卖第: 67张票
    Thread-0 正在卖第: 64张票
    Thread-2 正在卖第: 64张票
    Thread-1 正在卖第: 64张票
    Thread-0 正在卖第: 61张票
    Thread-1 正在卖第: 61张票
    Thread-2 正在卖第: 61张票
    Thread-1 正在卖第: 58张票
    Thread-0 正在卖第: 58张票
    Thread-2 正在卖第: 58张票
    Thread-0 正在卖第: 55张票
    Thread-2 正在卖第: 54张票
    Thread-1 正在卖第: 54张票
    Thread-2 正在卖第: 52张票
    Thread-1 正在卖第: 52张票
    Thread-0 正在卖第: 52张票
    Thread-2 正在卖第: 49张票
    Thread-1 正在卖第: 49张票
    Thread-0 正在卖第: 48张票
    Thread-1 正在卖第: 46张票
    Thread-2 正在卖第: 45张票
    Thread-0 正在卖第: 46张票
    Thread-0 正在卖第: 43张票
    Thread-2 正在卖第: 43张票
    Thread-1 正在卖第: 43张票
    Thread-1 正在卖第: 40张票
    Thread-2 正在卖第: 40张票
    Thread-0 正在卖第: 40张票
    Thread-0 正在卖第: 37张票
    Thread-2 正在卖第: 37张票
    Thread-1 正在卖第: 37张票
    Thread-1 正在卖第: 34张票
    Thread-0 正在卖第: 33张票
    Thread-2 正在卖第: 32张票
    Thread-1 正在卖第: 31张票
    Thread-0 正在卖第: 31张票
    Thread-2 正在卖第: 30张票
    Thread-2 正在卖第: 28张票
    Thread-1 正在卖第: 28张票
    Thread-0 正在卖第: 28张票
    Thread-0 正在卖第: 25张票
    Thread-2 正在卖第: 25张票
    Thread-1 正在卖第: 25张票
    Thread-2 正在卖第: 22张票
    Thread-1 正在卖第: 22张票
    Thread-0 正在卖第: 22张票
    Thread-1 正在卖第: 19张票
    Thread-0 正在卖第: 19张票
    Thread-2 正在卖第: 19张票
    Thread-2 正在卖第: 16张票
    Thread-1 正在卖第: 16张票
    Thread-0 正在卖第: 16张票
    Thread-0 正在卖第: 13张票
    Thread-1 正在卖第: 13张票
    Thread-2 正在卖第: 13张票
    Thread-2 正在卖第: 10张票
    Thread-1 正在卖第: 9张票
    Thread-0 正在卖第: 9张票
    Thread-2 正在卖第: 7张票
    Thread-1 正在卖第: 7张票
    Thread-0 正在卖第: 7张票
    Thread-0 正在卖第: 4张票
    Thread-2 正在卖第: 4张票
    Thread-1 正在卖第: 3张票
    Thread-2 正在卖第: 1张票
    Thread-0 正在卖第: 1张票
    Thread-1 正在卖第: 1张票
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    1. 多线程安全问题的解决

      多线程的同步来解决线程安全问题,多线程的同步可以有以下三种实现方式:

      • 同步代码块
      • 同步方法
      • 锁机制

      ①同步代码块:synchronized关键字可以用于方法中的某个区块中,表示只对这个区块的资源进行互斥访问

      格式:

      synchronized(同步锁){

      需要同步操作的代码

      }

      同步锁:对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁

      1. 锁对象可以是任一类型

      2. 多个线程对象,要使用同一把锁

        注意:多个线程在任何时候,都最多允许只有一个线程拿到这个同步锁,谁拿到同步锁谁就进入代码块,其他线程则必须等待(BLOCKED)

        //在重写runnalbe的类中加入一个object(任一)的锁对象,同时在重写run方法时,在其中修改共享数据的语句包裹在synchronizede中
        /*
        * 同步代码块解决实现卖票案例中出现的线程安全问题
        * */
        public class RunnableImpl implements Runnable{
            private int ticket = 100;
            //创建一个锁对象
            Object object = new Object();
            @Override
            public void run() {
                while (true){
                    synchronized (object){
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if (ticket>0) {
                            System.out.println(Thread.currentThread().getName()+" 正在卖第: "+ ticket +"张票");
                            ticket--;
                        }
                    }
                }
            }
        }
        //主方法不变,继续让三个线程来执行这个run方法
        /*
        * 创建三个线程让这三个线程都对共享的票进行出售
        * 共享体现在只有一个runnable的实现类,但是用三个线程来执行
        * */
        public class DemoMain {
            public static void main(String[] args) {
                RunnableImpl run = new RunnableImpl();
                Thread t1 = new Thread(run);
                Thread t2 = new Thread(run);
                Thread t3 = new Thread(run);
                t1.start();
                t2.start();
                t3.start();
        
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42

        打印结果能看到,解决了线程安全问题:

        Thread-0 正在卖第: 100张票
        Thread-0 正在卖第: 99张票
        Thread-0 正在卖第: 98张票
        Thread-0 正在卖第: 97张票
        Thread-0 正在卖第: 96张票
        Thread-0 正在卖第: 95张票
        Thread-0 正在卖第: 94张票
        Thread-0 正在卖第: 93张票
        Thread-0 正在卖第: 92张票
        Thread-0 正在卖第: 91张票
        Thread-0 正在卖第: 90张票
        Thread-0 正在卖第: 89张票
        Thread-0 正在卖第: 88张票
        Thread-0 正在卖第: 87张票
        Thread-0 正在卖第: 86张票
        Thread-0 正在卖第: 85张票
        Thread-0 正在卖第: 84张票
        Thread-0 正在卖第: 83张票
        Thread-0 正在卖第: 82张票
        Thread-0 正在卖第: 81张票
        Thread-0 正在卖第: 80张票
        Thread-0 正在卖第: 79张票
        Thread-0 正在卖第: 78张票
        Thread-0 正在卖第: 77张票
        Thread-0 正在卖第: 76张票
        Thread-0 正在卖第: 75张票
        Thread-0 正在卖第: 74张票
        Thread-0 正在卖第: 73张票
        Thread-0 正在卖第: 72张票
        Thread-0 正在卖第: 71张票
        Thread-0 正在卖第: 70张票
        Thread-0 正在卖第: 69张票
        Thread-0 正在卖第: 68张票
        Thread-0 正在卖第: 67张票
        Thread-0 正在卖第: 66张票
        Thread-0 正在卖第: 65张票
        Thread-0 正在卖第: 64张票
        Thread-0 正在卖第: 63张票
        Thread-0 正在卖第: 62张票
        Thread-0 正在卖第: 61张票
        Thread-0 正在卖第: 60张票
        Thread-0 正在卖第: 59张票
        Thread-1 正在卖第: 58张票
        Thread-1 正在卖第: 57张票
        Thread-1 正在卖第: 56张票
        Thread-1 正在卖第: 55张票
        Thread-1 正在卖第: 54张票
        Thread-1 正在卖第: 53张票
        Thread-1 正在卖第: 52张票
        Thread-1 正在卖第: 51张票
        Thread-2 正在卖第: 50张票
        Thread-2 正在卖第: 49张票
        Thread-2 正在卖第: 48张票
        Thread-2 正在卖第: 47张票
        Thread-2 正在卖第: 46张票
        Thread-2 正在卖第: 45张票
        Thread-2 正在卖第: 44张票
        Thread-2 正在卖第: 43张票
        Thread-2 正在卖第: 42张票
        Thread-2 正在卖第: 41张票
        Thread-2 正在卖第: 40张票
        Thread-2 正在卖第: 39张票
        Thread-2 正在卖第: 38张票
        Thread-2 正在卖第: 37张票
        Thread-2 正在卖第: 36张票
        Thread-2 正在卖第: 35张票
        Thread-2 正在卖第: 34张票
        Thread-2 正在卖第: 33张票
        Thread-2 正在卖第: 32张票
        Thread-2 正在卖第: 31张票
        Thread-2 正在卖第: 30张票
        Thread-2 正在卖第: 29张票
        Thread-2 正在卖第: 28张票
        Thread-2 正在卖第: 27张票
        Thread-2 正在卖第: 26张票
        Thread-2 正在卖第: 25张票
        Thread-2 正在卖第: 24张票
        Thread-2 正在卖第: 23张票
        Thread-1 正在卖第: 22张票
        Thread-1 正在卖第: 21张票
        Thread-1 正在卖第: 20张票
        Thread-1 正在卖第: 19张票
        Thread-1 正在卖第: 18张票
        Thread-1 正在卖第: 17张票
        Thread-1 正在卖第: 16张票
        Thread-1 正在卖第: 15张票
        Thread-1 正在卖第: 14张票
        Thread-1 正在卖第: 13张票
        Thread-1 正在卖第: 12张票
        Thread-1 正在卖第: 11张票
        Thread-1 正在卖第: 10张票
        Thread-1 正在卖第: 9张票
        Thread-1 正在卖第: 8张票
        Thread-1 正在卖第: 7张票
        Thread-1 正在卖第: 6张票
        Thread-1 正在卖第: 5张票
        Thread-1 正在卖第: 4张票
        Thread-1 正在卖第: 3张票
        Thread-1 正在卖第: 2张票
        Thread-1 正在卖第: 1张票
        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61
        • 62
        • 63
        • 64
        • 65
        • 66
        • 67
        • 68
        • 69
        • 70
        • 71
        • 72
        • 73
        • 74
        • 75
        • 76
        • 77
        • 78
        • 79
        • 80
        • 81
        • 82
        • 83
        • 84
        • 85
        • 86
        • 87
        • 88
        • 89
        • 90
        • 91
        • 92
        • 93
        • 94
        • 95
        • 96
        • 97
        • 98
        • 99
        • 100
        • 101

        同步代码块原理

      在这里插入图片描述

      ②同步方法:使用synchronized修饰的方法就叫做,同步方法,保证线程A在使用该方法的时候,其他方法只能在方法外等待

      格式:

      修饰符 synchronized 返回值类型 方法名(参数列表){

      ​ //可能会产生线程安全问题的代码

      }

      同步锁:

      在同步非静态方法中,同步锁就是this

      在静态方法中,同步锁就是类的字节码对象(类名.class)

      //在Runnable的实现类中,重新定义一个非静态同步方法,把可能产生线程安全问题的代码写入该方法中
      //在run方法中去调用该同步方法、
      /*
      * 同步方法结局卖票案例中的线程安全问题
      * */
      public class RunnableImpl implements Runnable{
          private int ticket = 100;
          @Override
          public void run() {
              while (true){
                  sellTicket();
              }
          }
          public synchronized void sellTicket(){
              try {
                  Thread.sleep(10);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              if (ticket>0) {
                  System.out.println(Thread.currentThread().getName()+" 正在卖第: "+ ticket +"张票");
                  ticket--;
              }
          }
      }
      //主方法不变,三个线程去调用run方法
      //在同步非静态方法中,同步锁就是this 在这个例子中就是new的对象run
      /*
      * 创建三个线程让这三个线程都对共享的票进行出售
      * 共享体现在只有一个runnable的实现类,但是用三个线程来执行
      * */
      public class DemoMain {
          public static void main(String[] args) {
              RunnableImpl run = new RunnableImpl();
              Thread t1 = new Thread(run);
              Thread t2 = new Thread(run);
              Thread t3 = new Thread(run);
              t1.start();
              t2.start();
              t3.start();
      
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43

      打印结果:解决线程安全问题

      Thread-0 正在卖第: 100张票
      Thread-0 正在卖第: 99张票
      Thread-0 正在卖第: 98张票
      Thread-0 正在卖第: 97张票
      Thread-0 正在卖第: 96张票
      Thread-0 正在卖第: 95张票
      Thread-0 正在卖第: 94张票
      Thread-0 正在卖第: 93张票
      Thread-0 正在卖第: 92张票
      Thread-0 正在卖第: 91张票
      Thread-0 正在卖第: 90张票
      Thread-0 正在卖第: 89张票
      Thread-0 正在卖第: 88张票
      Thread-0 正在卖第: 87张票
      Thread-0 正在卖第: 86张票
      Thread-0 正在卖第: 85张票
      Thread-0 正在卖第: 84张票
      Thread-0 正在卖第: 83张票
      Thread-2 正在卖第: 82张票
      Thread-2 正在卖第: 81张票
      Thread-2 正在卖第: 80张票
      Thread-2 正在卖第: 79张票
      Thread-2 正在卖第: 78张票
      Thread-2 正在卖第: 77张票
      Thread-2 正在卖第: 76张票
      Thread-2 正在卖第: 75张票
      Thread-2 正在卖第: 74张票
      Thread-2 正在卖第: 73张票
      Thread-2 正在卖第: 72张票
      Thread-2 正在卖第: 71张票
      Thread-2 正在卖第: 70张票
      Thread-2 正在卖第: 69张票
      Thread-2 正在卖第: 68张票
      Thread-2 正在卖第: 67张票
      Thread-2 正在卖第: 66张票
      Thread-1 正在卖第: 65张票
      Thread-1 正在卖第: 64张票
      Thread-1 正在卖第: 63张票
      Thread-1 正在卖第: 62张票
      Thread-1 正在卖第: 61张票
      Thread-1 正在卖第: 60张票
      Thread-1 正在卖第: 59张票
      Thread-1 正在卖第: 58张票
      Thread-1 正在卖第: 57张票
      Thread-1 正在卖第: 56张票
      Thread-1 正在卖第: 55张票
      Thread-1 正在卖第: 54张票
      Thread-1 正在卖第: 53张票
      Thread-1 正在卖第: 52张票
      Thread-1 正在卖第: 51张票
      Thread-1 正在卖第: 50张票
      Thread-1 正在卖第: 49张票
      Thread-1 正在卖第: 48张票
      Thread-1 正在卖第: 47张票
      Thread-1 正在卖第: 46张票
      Thread-1 正在卖第: 45张票
      Thread-1 正在卖第: 44张票
      Thread-1 正在卖第: 43张票
      Thread-1 正在卖第: 42张票
      Thread-1 正在卖第: 41张票
      Thread-1 正在卖第: 40张票
      Thread-1 正在卖第: 39张票
      Thread-1 正在卖第: 38张票
      Thread-1 正在卖第: 37张票
      Thread-1 正在卖第: 36张票
      Thread-1 正在卖第: 35张票
      Thread-1 正在卖第: 34张票
      Thread-1 正在卖第: 33张票
      Thread-1 正在卖第: 32张票
      Thread-1 正在卖第: 31张票
      Thread-1 正在卖第: 30张票
      Thread-1 正在卖第: 29张票
      Thread-2 正在卖第: 28张票
      Thread-2 正在卖第: 27张票
      Thread-2 正在卖第: 26张票
      Thread-2 正在卖第: 25张票
      Thread-2 正在卖第: 24张票
      Thread-2 正在卖第: 23张票
      Thread-2 正在卖第: 22张票
      Thread-2 正在卖第: 21张票
      Thread-2 正在卖第: 20张票
      Thread-2 正在卖第: 19张票
      Thread-2 正在卖第: 18张票
      Thread-2 正在卖第: 17张票
      Thread-2 正在卖第: 16张票
      Thread-0 正在卖第: 15张票
      Thread-0 正在卖第: 14张票
      Thread-0 正在卖第: 13张票
      Thread-0 正在卖第: 12张票
      Thread-0 正在卖第: 11张票
      Thread-0 正在卖第: 10张票
      Thread-0 正在卖第: 9张票
      Thread-0 正在卖第: 8张票
      Thread-0 正在卖第: 7张票
      Thread-0 正在卖第: 6张票
      Thread-0 正在卖第: 5张票
      Thread-0 正在卖第: 4张票
      Thread-0 正在卖第: 3张票
      Thread-0 正在卖第: 2张票
      Thread-0 正在卖第: 1张票
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92
      • 93
      • 94
      • 95
      • 96
      • 97
      • 98
      • 99
      • 100

      静态同步方法:

      //在Runnable的实现类中,重新定义一个静态同步方法,把可能产生线程安全问题的代码写入该方法中
      //在run方法中去调用该同步方法、
      /*
      * 同步方法结局卖票案例中的线程安全问题
      * */
      public class RunnableImpl implements Runnable{
          private static int ticket = 100;
          @Override
          public void run() {
              while (true){
                  sellTicketStatic();
              }
          }
          public static synchronized void sellTicketStatic(){
              try {
                  Thread.sleep(10);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              if (ticket>0) {
                  System.out.println(Thread.currentThread().getName()+" 正在卖第: "+ ticket +"张票");
                  ticket--;
              }
          }
      
      }
      //主方法开启三个线程去执行run方法
      /*
      * 创建三个线程让这三个线程都对共享的票进行出售
      * 共享体现在只有一个runnable的实现类,但是用三个线程来执行
      此时静态方法的锁对象就是 Runnable.class
      * */
      public class DemoMain {
          public static void main(String[] args) {
              RunnableImpl run = new RunnableImpl();
              Thread t1 = new Thread(run);
              Thread t2 = new Thread(run);
              Thread t3 = new Thread(run);
              t1.start();
              t2.start();
              t3.start();
      
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44

      打印结果:依然是解决了线程安全问题

      Thread-0 正在卖第: 100张票
      Thread-0 正在卖第: 99张票
      Thread-0 正在卖第: 98张票
      Thread-0 正在卖第: 97张票
      Thread-0 正在卖第: 96张票
      Thread-0 正在卖第: 95张票
      Thread-0 正在卖第: 94张票
      Thread-2 正在卖第: 93张票
      Thread-2 正在卖第: 92张票
      Thread-2 正在卖第: 91张票
      Thread-2 正在卖第: 90张票
      Thread-2 正在卖第: 89张票
      Thread-2 正在卖第: 88张票
      Thread-2 正在卖第: 87张票
      Thread-2 正在卖第: 86张票
      Thread-2 正在卖第: 85张票
      Thread-2 正在卖第: 84张票
      Thread-2 正在卖第: 83张票
      Thread-2 正在卖第: 82张票
      Thread-2 正在卖第: 81张票
      Thread-2 正在卖第: 80张票
      Thread-2 正在卖第: 79张票
      Thread-2 正在卖第: 78张票
      Thread-2 正在卖第: 77张票
      Thread-2 正在卖第: 76张票
      Thread-2 正在卖第: 75张票
      Thread-2 正在卖第: 74张票
      Thread-2 正在卖第: 73张票
      Thread-2 正在卖第: 72张票
      Thread-2 正在卖第: 71张票
      Thread-1 正在卖第: 70张票
      Thread-1 正在卖第: 69张票
      Thread-1 正在卖第: 68张票
      Thread-1 正在卖第: 67张票
      Thread-1 正在卖第: 66张票
      Thread-1 正在卖第: 65张票
      Thread-1 正在卖第: 64张票
      Thread-1 正在卖第: 63张票
      Thread-1 正在卖第: 62张票
      Thread-1 正在卖第: 61张票
      Thread-1 正在卖第: 60张票
      Thread-1 正在卖第: 59张票
      Thread-1 正在卖第: 58张票
      Thread-1 正在卖第: 57张票
      Thread-2 正在卖第: 56张票
      Thread-2 正在卖第: 55张票
      Thread-2 正在卖第: 54张票
      Thread-0 正在卖第: 53张票
      Thread-0 正在卖第: 52张票
      Thread-0 正在卖第: 51张票
      Thread-0 正在卖第: 50张票
      Thread-0 正在卖第: 49张票
      Thread-0 正在卖第: 48张票
      Thread-0 正在卖第: 47张票
      Thread-0 正在卖第: 46张票
      Thread-0 正在卖第: 45张票
      Thread-0 正在卖第: 44张票
      Thread-0 正在卖第: 43张票
      Thread-0 正在卖第: 42张票
      Thread-0 正在卖第: 41张票
      Thread-0 正在卖第: 40张票
      Thread-0 正在卖第: 39张票
      Thread-0 正在卖第: 38张票
      Thread-0 正在卖第: 37张票
      Thread-0 正在卖第: 36张票
      Thread-0 正在卖第: 35张票
      Thread-0 正在卖第: 34张票
      Thread-0 正在卖第: 33张票
      Thread-0 正在卖第: 32张票
      Thread-0 正在卖第: 31张票
      Thread-2 正在卖第: 30张票
      Thread-2 正在卖第: 29张票
      Thread-2 正在卖第: 28张票
      Thread-2 正在卖第: 27张票
      Thread-1 正在卖第: 26张票
      Thread-1 正在卖第: 25张票
      Thread-1 正在卖第: 24张票
      Thread-1 正在卖第: 23张票
      Thread-1 正在卖第: 22张票
      Thread-1 正在卖第: 21张票
      Thread-1 正在卖第: 20张票
      Thread-1 正在卖第: 19张票
      Thread-1 正在卖第: 18张票
      Thread-1 正在卖第: 17张票
      Thread-1 正在卖第: 16张票
      Thread-1 正在卖第: 15张票
      Thread-1 正在卖第: 14张票
      Thread-1 正在卖第: 13张票
      Thread-1 正在卖第: 12张票
      Thread-1 正在卖第: 11张票
      Thread-1 正在卖第: 10张票
      Thread-1 正在卖第: 9张票
      Thread-1 正在卖第: 8张票
      Thread-1 正在卖第: 7张票
      Thread-1 正在卖第: 6张票
      Thread-1 正在卖第: 5张票
      Thread-1 正在卖第: 4张票
      Thread-1 正在卖第: 3张票
      Thread-1 正在卖第: 2张票
      Thread-1 正在卖第: 1张票
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92
      • 93
      • 94
      • 95
      • 96
      • 97
      • 98
      • 99
      • 100

      ③Lock锁

      java.util.concurrent.locks.Lock机制提供比使用synchronized方法和语句可以获得的更广泛的锁定操作。同步代码块/同步方法所具有的的方法,Lock都有,除此之外还更强大,更体现面向对象

      • public interface Lock
        
        • 1

        Lock实现提供比使用synchronized方法和语句可以获得的更广泛的锁定操作。它们允许更灵活的结构化,可能具有完全不同的属性,并且可以支持多个相关联的对象Condition

        锁是用于通过多个线程控制对共享资源的访问的工具。 通常,锁提供对共享资源的独占访问:一次只能有一个线程可以获取锁,并且对共享资源的所有访问都要求首先获取锁。 但是,一些锁可能允许并发访问共享资源,如ReadWriteLock的读锁。

        使用synchronized方法或语句提供对与每个对象相关联的隐式监视器锁的访问,但是强制所有锁获取和释放以块结构的方式发生:当获取多个锁时,它们必须以相反的顺序被释放,并且所有的锁都必须被释放在与它们相同的词汇范围内。

        虽然synchronized方法和语句的范围机制使得使用监视器锁更容易编程,并且有助于避免涉及锁的许多常见编程错误,但是有时您需要以更灵活的方式处理锁。 例如,用于遍历并发访问的数据结构的一些算法需要使用“手动”或“链锁定”:您获取节点A的锁定,然后获取节点B,然后释放A并获取C,然后释放B并获得D等。 所述的实施方式中Lock接口通过允许获得并在不同的范围释放的锁,并允许获得并以任何顺序释放多个锁使得能够使用这样的技术。

      • 同时加锁和解锁进行方法化

        void lock():获得锁

        void unlock():释放锁

      • 代码实现:

        /*
        * 使用Lock锁来解决卖票案例中产生的线程安全问题
        * Lock的实现类:java.util.concurrent.locks.ReentrantLock implements Lock
         * 使用步骤:1.在Runnable实现类的成员位置创建Lock的实现类
         *         2.在可能出现安全问题的代码处调用Lock的方法void lock();获取锁
         *         3.在可能出现安全问题的代码后调用Lock的方法void unlock();方法解锁
        *
         * */
        public class RunnableImpl implements Runnable{
            private int ticket = 100;
            //1.在Runnable实现类的成员位置创建Lock的实现类
            Lock lock = new ReentrantLock();
            @Override
            public void run() {
                while (true){
                    //2.在可能出现安全问题的代码处调用Lock的方法void lock();获取锁
                    lock.lock();
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (ticket>0) {
                        System.out.println(Thread.currentThread().getName()+" 正在卖第: "+ ticket +"张票");
                        ticket--;
                    }
                    //3.在可能出现安全问题的代码后调用Lock的方法void unlock();方法解锁
                    lock.unlock();
                }
            }
        }
        //主方法开启三个线程
        /*
        * 创建三个线程让这三个线程都对共享的票进行出售
        * 共享体现在只有一个runnable的实现类,但是用三个线程来执行
        * */
        public class DemoMain {
            public static void main(String[] args) {
                RunnableImpl run = new RunnableImpl();
                Thread t1 = new Thread(run);
                Thread t2 = new Thread(run);
                Thread t3 = new Thread(run);
                t1.start();
                t2.start();
                t3.start();
        
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48

        打印结果:解决了线程安全问题

        Thread-0 正在卖第: 100张票
        Thread-0 正在卖第: 99张票
        Thread-0 正在卖第: 98张票
        Thread-0 正在卖第: 97张票
        Thread-0 正在卖第: 96张票
        Thread-0 正在卖第: 95张票
        Thread-0 正在卖第: 94张票
        Thread-0 正在卖第: 93张票
        Thread-0 正在卖第: 92张票
        Thread-0 正在卖第: 91张票
        Thread-0 正在卖第: 90张票
        Thread-0 正在卖第: 89张票
        Thread-0 正在卖第: 88张票
        Thread-0 正在卖第: 87张票
        Thread-0 正在卖第: 86张票
        Thread-0 正在卖第: 85张票
        Thread-0 正在卖第: 84张票
        Thread-0 正在卖第: 83张票
        Thread-0 正在卖第: 82张票
        Thread-0 正在卖第: 81张票
        Thread-0 正在卖第: 80张票
        Thread-0 正在卖第: 79张票
        Thread-0 正在卖第: 78张票
        Thread-0 正在卖第: 77张票
        Thread-0 正在卖第: 76张票
        Thread-1 正在卖第: 75张票
        Thread-1 正在卖第: 74张票
        Thread-1 正在卖第: 73张票
        Thread-1 正在卖第: 72张票
        Thread-1 正在卖第: 71张票
        Thread-1 正在卖第: 70张票
        Thread-1 正在卖第: 69张票
        Thread-1 正在卖第: 68张票
        Thread-1 正在卖第: 67张票
        Thread-1 正在卖第: 66张票
        Thread-1 正在卖第: 65张票
        Thread-1 正在卖第: 64张票
        Thread-1 正在卖第: 63张票
        Thread-1 正在卖第: 62张票
        Thread-1 正在卖第: 61张票
        Thread-1 正在卖第: 60张票
        Thread-1 正在卖第: 59张票
        Thread-1 正在卖第: 58张票
        Thread-1 正在卖第: 57张票
        Thread-1 正在卖第: 56张票
        Thread-1 正在卖第: 55张票
        Thread-1 正在卖第: 54张票
        Thread-1 正在卖第: 53张票
        Thread-1 正在卖第: 52张票
        Thread-1 正在卖第: 51张票
        Thread-1 正在卖第: 50张票
        Thread-1 正在卖第: 49张票
        Thread-1 正在卖第: 48张票
        Thread-1 正在卖第: 47张票
        Thread-1 正在卖第: 46张票
        Thread-1 正在卖第: 45张票
        Thread-1 正在卖第: 44张票
        Thread-1 正在卖第: 43张票
        Thread-1 正在卖第: 42张票
        Thread-1 正在卖第: 41张票
        Thread-1 正在卖第: 40张票
        Thread-1 正在卖第: 39张票
        Thread-1 正在卖第: 38张票
        Thread-1 正在卖第: 37张票
        Thread-1 正在卖第: 36张票
        Thread-1 正在卖第: 35张票
        Thread-1 正在卖第: 34张票
        Thread-1 正在卖第: 33张票
        Thread-1 正在卖第: 32张票
        Thread-1 正在卖第: 31张票
        Thread-1 正在卖第: 30张票
        Thread-1 正在卖第: 29张票
        Thread-1 正在卖第: 28张票
        Thread-1 正在卖第: 27张票
        Thread-1 正在卖第: 26张票
        Thread-1 正在卖第: 25张票
        Thread-1 正在卖第: 24张票
        Thread-1 正在卖第: 23张票
        Thread-1 正在卖第: 22张票
        Thread-1 正在卖第: 21张票
        Thread-1 正在卖第: 20张票
        Thread-1 正在卖第: 19张票
        Thread-1 正在卖第: 18张票
        Thread-1 正在卖第: 17张票
        Thread-1 正在卖第: 16张票
        Thread-1 正在卖第: 15张票
        Thread-1 正在卖第: 14张票
        Thread-1 正在卖第: 13张票
        Thread-1 正在卖第: 12张票
        Thread-1 正在卖第: 11张票
        Thread-1 正在卖第: 10张票
        Thread-1 正在卖第: 9张票
        Thread-1 正在卖第: 8张票
        Thread-1 正在卖第: 7张票
        Thread-1 正在卖第: 6张票
        Thread-1 正在卖第: 5张票
        Thread-1 正在卖第: 4张票
        Thread-1 正在卖第: 3张票
        Thread-1 正在卖第: 2张票
        Thread-1 正在卖第: 1张票
        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61
        • 62
        • 63
        • 64
        • 65
        • 66
        • 67
        • 68
        • 69
        • 70
        • 71
        • 72
        • 73
        • 74
        • 75
        • 76
        • 77
        • 78
        • 79
        • 80
        • 81
        • 82
        • 83
        • 84
        • 85
        • 86
        • 87
        • 88
        • 89
        • 90
        • 91
        • 92
        • 93
        • 94
        • 95
        • 96
        • 97
        • 98
        • 99
        • 100
        • 101
           可以看API文档优化以下lock锁部分,把unlock放到finally
        
        • 1
    public class RunnableImpl implements Runnable{
        private int ticket = 100;
        //1.在Runnable实现类的成员位置创建Lock的实现类
        Lock lock = new ReentrantLock();
        @Override
        public void run() {
            while (true){
                //2.在可能出现安全问题的代码处调用Lock的方法void lock();获取锁
                lock.lock();
                try {
                    Thread.sleep(10);
                    if (ticket>0) {
                        System.out.println(Thread.currentThread().getName()+" 正在卖第: "+ ticket +"张票");
                        ticket--;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    //3.在可能出现安全问题的代码后调用Lock的方法void unlock();方法解锁
                    lock.unlock();//无论程序是否异常都会把锁给释放掉,提高程序效率
                }
    
    
            }
        }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
  • 相关阅读:
    一文理解GIT的代码冲突
    【填坑】乐鑫ESP32C3 Bootloader开发(上)
    redo log 和 binlog 的一些总结
    MacOS M1 lotus 源码编译
    CSS 链接:Link
    Pytorch实用教程:nn.CrossEntropyLoss()的用法
    01-MySQL简介和安装
    LeetCode 第 311 场周赛
    MySQL入门指南6(视图,用户管理,存储引擎,数据类型)
    【论文阅读】【yolo系列】YOLO-Pose的论文阅读
  • 原文地址:https://blog.csdn.net/karenkou/article/details/126127006