Day 65

_同步代码块解决数据安全问题

  1. 出现数据安全问题的原因:

    • 是否是多线程环境
    • 是否有共享数据
    • 是否有多条语句操作共享数据
  2. 如何解决多线程安全问题:基本思想—>让程序在没有安全问题的环境运行

    实现方法:

    • 把多条语句操作共享数据的代码给锁起来,让任意时刻都只能有一个线程执行即可
    • java提供红了同步代码块的方式来解决
  3. 同步方法:就是把synchronized关键字加到方法上

    • 格式:修饰符 synchronized 返回值类型 方法名(方法参数){}
      • 同步方法的锁对象是:—> this
  4. 同步静态方法:就是把synchronized关键字加到静态方法上

    • 格式:修饰符 static synchronized 返回值类型 方法名(方法参数){}
      • 同步静态方法的锁的对象是:—> 类名.class
  5. package demo19;
    
    public class Thread_Demo_02 {
        public static void main(String[] args) {
            /*
            1. 出现数据安全问题的原因:
               - 是否是多线程环境
               - 是否有共享数据
               - 是否有多条语句操作共享数据
            2. 如何解决多线程安全问题:基本思想--->让程序在没有安全问题的环境运行
               实现方法:
               - 把多条语句操作共享数据的代码给锁起来,让任意时刻都只能有一个线程执行即可
               - java提供红了同步代码块的方式来解决
             */
    
            SellTickets_02 st = new SellTickets_02();
    
            Thread t1 = new Thread(st, "窗口一");
            Thread t2 = new Thread(st, "窗口二");
            Thread t3 = new Thread(st, "窗口三");
    
            t1.start();
            t2.start();
            t3.start();
        }
    }
    --------------------------------------------
    package demo19;
    
    public class SellTickets_02 implements Runnable{
        private int tickets = 100;
        private Object obj  = new Object();
        @Override
        public void run() {
            while (true) {
                synchronized (obj) {
                    if (tickets > 0) {
                        System.out.println(Thread.currentThread().getName() + "正在售出第" + tickets + "张票");
                        tickets--;
                    }
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    ====================================
    窗口一正在售出第100张票
    窗口三正在售出第99张票
    窗口二正在售出第98张票
    窗口二正在售出第97张票
    窗口三正在售出第96张票
    窗口三正在售出第95张票
    窗口一正在售出第94张票
    窗口一正在售出第93张票
    窗口一正在售出第92张票
    窗口一正在售出第91张票
    窗口一正在售出第90张票
    窗口三正在售出第89张票
    窗口三正在售出第88张票
    窗口三正在售出第87张票
    窗口三正在售出第86张票
    窗口二正在售出第85张票
    窗口二正在售出第84张票
    窗口三正在售出第83张票
    窗口三正在售出第82张票
    窗口三正在售出第81张票
    窗口一正在售出第80张票
    窗口三正在售出第79张票
    窗口三正在售出第78张票
    窗口二正在售出第77张票
    窗口二正在售出第76张票
    窗口三正在售出第75张票
    窗口三正在售出第74张票
    窗口三正在售出第73张票
    窗口一正在售出第72张票
    窗口三正在售出第71张票
    窗口二正在售出第70张票
    窗口三正在售出第69张票
    窗口一正在售出第68张票
    窗口三正在售出第67张票
    窗口三正在售出第66张票
    窗口二正在售出第65张票
    窗口二正在售出第64张票
    窗口二正在售出第63张票
    窗口二正在售出第62张票
    窗口三正在售出第61张票
    窗口一正在售出第60张票
    窗口一正在售出第59张票
    窗口三正在售出第58张票
    窗口二正在售出第57张票
    窗口三正在售出第56张票
    窗口一正在售出第55张票
    窗口一正在售出第54张票
    窗口一正在售出第53张票
    窗口三正在售出第52张票
    窗口二正在售出第51张票
    窗口二正在售出第50张票
    窗口二正在售出第49张票
    窗口二正在售出第48张票
    窗口三正在售出第47张票
    窗口三正在售出第46张票
    窗口三正在售出第45张票
    窗口三正在售出第44张票
    窗口一正在售出第43张票
    窗口一正在售出第42张票
    窗口三正在售出第41张票
    窗口三正在售出第40张票
    窗口二正在售出第39张票
    窗口三正在售出第38张票
    窗口一正在售出第37张票
    窗口三正在售出第36张票
    窗口二正在售出第35张票
    窗口三正在售出第34张票
    窗口三正在售出第33张票
    窗口一正在售出第32张票
    窗口三正在售出第31张票
    窗口三正在售出第30张票
    窗口二正在售出第29张票
    窗口三正在售出第28张票
    窗口三正在售出第27张票
    窗口一正在售出第26张票
    窗口一正在售出第25张票
    窗口一正在售出第24张票
    窗口一正在售出第23张票
    窗口三正在售出第22张票
    窗口三正在售出第21张票
    窗口二正在售出第20张票
    窗口三正在售出第19张票
    窗口三正在售出第18张票
    窗口三正在售出第17张票
    窗口三正在售出第16张票
    窗口一正在售出第15张票
    窗口三正在售出第14张票
    窗口二正在售出第13张票
    窗口三正在售出第12张票
    窗口一正在售出第11张票
    窗口一正在售出第10张票
    窗口三正在售出第9张票
    窗口三正在售出第8张票
    窗口三正在售出第7张票
    窗口三正在售出第6张票
    窗口二正在售出第5张票
    窗口三正在售出第4张票
    窗口三正在售出第3张票
    窗口一正在售出第2张票
    窗口一正在售出第1张票
    
    Process finished with exit code 130
    

_Lock锁

  1. 虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更加清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock

  2. Lock实现提供比使用synchronized方法和语句可以获得更广泛的锁定操作

    Lock中提供了获得锁和释放锁的方法

    • void lock():获得锁
    • void unlock:释放锁
  3. Lock是接口不能直接实例化,这里常采用它的实现类ReentrantLock来实例化

    ReentrantLock的构造方法

    • ReenTrantLock():创建一个ReentrantLock的实例
  4. package demo20;
    
    public class Lock_Demo_01 {
        public static void main(String[] args) {
            /*
            1. Lock实现提供比使用synchronized方法和语句可以获得更广泛的锁定操作
               Lock中提供了获得锁和释放锁的方法
    
               - void lock():获得锁
               - void unlock:释放锁
    
            2. **Lock是接口**不能直接实例化,这里常采用它的实现类ReentrantLock来实例化
               ReentrantLock的构造方法
               - ReentrantLock():创建一个ReentrantLock的实例
             */
    
            SellTickets_01 st = new SellTickets_01();
    
            Thread t1 = new Thread(st, "窗口1");
            Thread t2 = new Thread(st, "窗口2");
            Thread t3 = new Thread(st, "窗口3");
    
            t1.start();
            t2.start();
            t3.start();
    
        }
    }
    --------------------------------------------
    package demo20;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class SellTickets_01 implements Runnable {
        private int tickets = 100;
        private Lock lock = new ReentrantLock();
        @Override
        public void run() {
            while (tickets>0) {
                lock.lock();
                if (tickets > 0) {
                    System.out.println(Thread.currentThread().getName() + "正在售卖第" + tickets + "张票");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    tickets--;
                }
                lock.unlock();
            }
        }
    }
    =======================================
    窗口1正在售卖第100张票
    窗口1正在售卖第99张票
    窗口3正在售卖第98张票
    窗口2正在售卖第97张票
    窗口1正在售卖第96张票
    窗口3正在售卖第95张票
    窗口2正在售卖第94张票
    窗口1正在售卖第93张票
    窗口1正在售卖第92张票
    窗口1正在售卖第91张票
    窗口3正在售卖第90张票
    窗口3正在售卖第89张票
    窗口2正在售卖第88张票
    窗口2正在售卖第87张票
    窗口2正在售卖第86张票
    窗口1正在售卖第85张票
    窗口3正在售卖第84张票
    窗口2正在售卖第83张票
    窗口1正在售卖第82张票
    窗口1正在售卖第81张票
    窗口1正在售卖第80张票
    窗口3正在售卖第79张票
    窗口3正在售卖第78张票
    窗口2正在售卖第77张票
    窗口1正在售卖第76张票
    窗口1正在售卖第75张票
    窗口3正在售卖第74张票
    窗口3正在售卖第73张票
    窗口3正在售卖第72张票
    窗口3正在售卖第71张票
    窗口3正在售卖第70张票
    窗口3正在售卖第69张票
    窗口2正在售卖第68张票
    窗口2正在售卖第67张票
    窗口1正在售卖第66张票
    窗口1正在售卖第65张票
    窗口1正在售卖第64张票
    窗口1正在售卖第63张票
    窗口1正在售卖第62张票
    窗口1正在售卖第61张票
    窗口3正在售卖第60张票
    窗口3正在售卖第59张票
    窗口2正在售卖第58张票
    窗口1正在售卖第57张票
    窗口1正在售卖第56张票
    窗口1正在售卖第55张票
    窗口1正在售卖第54张票
    窗口3正在售卖第53张票
    窗口3正在售卖第52张票
    窗口3正在售卖第51张票
    窗口3正在售卖第50张票
    窗口3正在售卖第49张票
    窗口3正在售卖第48张票
    窗口3正在售卖第47张票
    窗口2正在售卖第46张票
    窗口2正在售卖第45张票
    窗口1正在售卖第44张票
    窗口1正在售卖第43张票
    窗口1正在售卖第42张票
    窗口1正在售卖第41张票
    窗口3正在售卖第40张票
    窗口2正在售卖第39张票
    窗口2正在售卖第38张票
    窗口2正在售卖第37张票
    窗口2正在售卖第36张票
    窗口2正在售卖第35张票
    窗口1正在售卖第34张票
    窗口1正在售卖第33张票
    窗口1正在售卖第32张票
    窗口1正在售卖第31张票
    窗口3正在售卖第30张票
    窗口3正在售卖第29张票
    窗口3正在售卖第28张票
    窗口3正在售卖第27张票
    窗口3正在售卖第26张票
    窗口3正在售卖第25张票
    窗口3正在售卖第24张票
    窗口3正在售卖第23张票
    窗口3正在售卖第22张票
    窗口3正在售卖第21张票
    窗口3正在售卖第20张票
    窗口3正在售卖第19张票
    窗口3正在售卖第18张票
    窗口3正在售卖第17张票
    窗口3正在售卖第16张票
    窗口3正在售卖第15张票
    窗口3正在售卖第14张票
    窗口3正在售卖第13张票
    窗口2正在售卖第12张票
    窗口2正在售卖第11张票
    窗口2正在售卖第10张票
    窗口2正在售卖第9张票
    窗口2正在售卖第8张票
    窗口2正在售卖第7张票
    窗口2正在售卖第6张票
    窗口2正在售卖第5张票
    窗口2正在售卖第4张票
    窗口2正在售卖第3张票
    窗口2正在售卖第2张票
    窗口2正在售卖第1张票
    
    Process finished with exit code 0
    

_生产者和消费者模式概述

  1. 生产者消费者模型是一个十分经典的多线程协作模式,弄清楚生产者和消费者问题能够让我们对多线程编程的理解更加深刻,所谓的生产者消费者问题,实际上主要是包含了两类线程:

    • 一类是生产者线程用于生产数据
    • 一类是消费者线程用于消费数据
  2. 为了解耦生产者和消费者的关系,通常会采用共享的数据区域,就像是一个仓库

    • 生产者生产数据之后直接防止在共享区域中,并不需要关心消费者的行为
    • 消费者只需要从共享数据中去获取数据,并不需要关心生产者的行为
  3. 为了体现生产和消费过程中的等待和唤醒,java就提供了几个方法供我们使用,这几个方法在Object类中

    方法名说明
    void wait()导致当前线程等待,直到另一个线程调用给对象的notify()方法或notifyAll()方法
    void notify()唤醒正在等待对象监视器的单个线程
    void notifyAll()唤醒正在等待对象监视器的所有线程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值