狂神说《多线程》卖早餐设置互斥锁
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++; } } } } }