zoukankan      html  css  js  c++  java
  • 狂神说《多线程》卖早餐设置互斥锁

    1. 先说一下为什么会出现一份早餐被多个窗口同时售卖,并且有时还会出现-1

      首先我先调整一下代码

      

      this.breakfast的加法不写在一起,单独成立一行,出现重复票与-1的情况更容易,(采用方式二:实现Runable接口的情况下)由于线程对共享资源(也就是早餐数)的消耗十分短暂,

    且一个线程本身执行的就很快,无法保证下一个售卖窗口(线程)在做加法(原视频用的减法)时breakfast数量是正确的,线程的启动无法控制,由cup调度决定。因此就得设置线程锁(网上查到是互斥锁)

    2. 完整代码(注释也挺多的,新人见解欢迎纠错)

      *************************说明一点:每次运行的结果是不一样的,我常看到弹幕里说龟兔赛跑的事,一个结果多运行几次,效果是不一样的!*******************************************

    package com.cy.Thread;
    
    
    /**
     * 初识并发问题,三个窗口共卖10分早餐
     */
    
    import com.sun.org.apache.xerces.internal.util.SynchronizedSymbolTable;
    
    /**
     * 本机i5 6400只有4核心4线程
     * 创建线程方式2:实现Runable接口,执行线程需丢入Runable的实现类
     */
    public class TestThread3 implements Runnable{
        private int breakfast =1;
        private boolean tag = true;// 标记为了停止线程
    
    
        @Override
        public void run() {
            while(this.tag){
                //非同步售卖
    //            saleBreakfast1();
    
                //同步售卖
                saleBreakfast2();
            }
        }
    
        public static void main(String[] args) {
    
            //创建Runable接口的实现类对象
            TestThread3 thread =new TestThread3();
    
            /**
             * 得有一个公共变量,也就是breakfast
             * 简洁写法(属于代理模式,相当于中介,前提是均得实现同一个接口)
             * 实现Runable可以达到同一个任务多线程执行,当然也可以像继承Thread那样各自完成各自的(多个干爹,所有工作共同承担)
             * 继承Thread 就只能各自完成各自的(只能有一个亲爹,所有工作一人来)
             */
             Thread t1 = new Thread(thread,"一号窗口");
             Thread t2 = new Thread(thread,"二号窗口");
             Thread t3 = new Thread(thread,"三号窗口");
    
    
             t1.start();
             t2.start();
             t3.start();
        }
    
        //不同步,可能同时卖同一份早餐,有可能最后还有一张票时候三者都操作导致得到0与-1
        public void saleBreakfast1(){
            while(true){
                //设置15份更容易三个窗口都出现,更直观
                if(this.breakfast > 15){  
                    break;
                }
                /**
                 * 模拟延迟
                 */
                try {
                    Thread.sleep(200);   //毫秒   1秒等于1000毫秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"在卖早餐---》"+(this.breakfast));
                /**
                 * 这里不写成breakfast++,而是单独一行是为了重现线程不同步导致的breakfast被重复售卖
                 * 因为你在做减法时,其他线程因为runable共享资源的原因就可能已经开始卖早餐了,因此得设置线程锁(互斥锁)
                 */
                this.breakfast++;
    
            }
        }
    
        //互斥锁
        public void saleBreakfast2() {
            synchronized(this){
                if (this.tag) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (this.breakfast > 15) {
                        tag=false;
                        return;
                    }
                    else{
                        System.out.println(Thread.currentThread().getName()+"在卖早餐---》"+(this.breakfast));
                        this.breakfast++;
    
                    }
                }
            }
    
        }
    
    }
  • 相关阅读:
    适用于小白的 python 快速入门教程
    Centos7.x & RedHat7.x系统忘记 root 密码解决办法
    让我来教你如何免费使用RHEL小红帽系统
    10#Windows注册表的那些事儿
    9#搭建网站
    8#继承和多态
    7#Java基本语句语法
    6#day2总结
    5#关于数据数值的转换
    .NET Core开发日志——配置
  • 原文地址:https://www.cnblogs.com/cybg/p/15545063.html
Copyright © 2011-2022 走看看