文章目录

  • 前言
  • 简单的原理: 队列+锁
  • 常见的买票案例(线程安全:多个线程操作同一个数据。)
    • 结果:
  • 使用同步代码块或者同步方法(解决线程不安全的问题)
    • 添加的方式一:synchronized 关键字
      • 结果:
      • 分析结果:
    • 添加方式二:代码块(注意位置)
      • 结果:
      • 结果分析:
    • 添加方式三:代码块(注意位置)
      • 结果:
      • 结果分析:
    • 添加方式四:代码块(注意位置)
      • 结果
      • 结果详解
  • 每次思考都会有收获。这次记录一下。

前言

复习多线程章节的时候有些疑问,想想后,理解的更深了。由此来记录以下。希望也可以帮助其他的人。


简单的原理: 队列+锁


常见的买票案例(线程安全:多个线程操作同一个数据。)

public class TestTicket02 implements Runnable{//库存中有 100 张票private int ticket = 100;//在这个方法中,进行买票@Overridepublic void run() {//怎么买票? 票没就结束//循环买票while(true){// 票没有了,就进行停止if(ticket <= 0){break;}//有票就进行卖票System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"票");//买了一张,就少一张票ticket--;}}public static void main(String[] args) {TestTicket02 testTicket02 = new TestTicket02();new Thread(testTicket02,"1").start();new Thread(testTicket02,"2").start();new Thread(testTicket02,"3").start();}
}


结果:

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


这里添加Thread.sleap(…) 有不同的结果。
会导致:
1
0
-1
的结果


使用同步代码块或者同步方法(解决线程不安全的问题)

添加的地方不同,会有不同的结果。


添加的方式一:synchronized 关键字

由于只进行修改run()中的代码所有,只显示这部分代码


@Overridepublic synchronized void run() {      //怎么买票? 票没就结束//循环买票while(true){// 票没有了,就进行停止if(ticket <= 0){break;}//有票就进行卖票System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"票");//买了一张,就少一张票ticket--;}}


结果:

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


分析结果:

线程名为1 的线程,执行了全部的票 。

  1. 为什么是线程名为1 的线程 执行? 原因:根据 cpu 自动调度的。
  2. 为什么线程1 执行了全部?
    原因:synchronized 标注在了run()方法上了。
    代表了,3个线程,进行排队(形成队列)停留在run()方法的前面,一个一个的等待执行。cpu调度,把锁(this)随机分配给任意的一个线程。(由于线程1先new ,所以先进行调度)。run()执行完了后,ticket等于0了,其他的线程拿到了锁,进入了run()中,由于ticket等于0,所以相当于没有执行。


添加方式二:代码块(注意位置)

//在这个方法中,进行买票@Overridepublic  void run() {synchronized(this){      //怎么买票? 票没就结束//循环买票while(true){// 票没有了,就进行停止if(ticket <= 0){break;}//有票就进行卖票System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"票");//买了一张,就少一张票ticket--;}}}


结果:

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


结果分析:

        1. 三个线程同时进入了run()方法中。在这个方法的前面进行停下来了。进行排队(队列),一个一个的执行该方法。当一个线程执行完后,ticket==0了,2,3线程拿到了this对象,不会执行什么了。和前面的结果一样。synchronized(this){     //怎么买票? 票没就结束//循环买票while(true){// 票没有了,就进行停止if(ticket <= 0){break;}//有票就进行卖票System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"票");//买了一张,就少一张票ticket--;}}

添加方式三:代码块(注意位置)

//在这个方法中,进行买票@Overridepublic  void run() {//怎么买票? 票没就结束//循环买票while(true){synchronized (this){// 票没有了,就进行停止if(ticket <= 0){break;}//有票就进行卖票System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"票");//买了一张,就少一张票ticket--;}}}

结果:

1买了第100票
1买了第99票
1买了第98票
1买了第97票
1买了第96票
1买了第95票
1买了第94票
1买了第93票
1买了第92票
1买了第91票
1买了第90票
1买了第89票
1买了第88票
1买了第87票
1买了第86票
1买了第85票
1买了第84票
1买了第83票
1买了第82票
1买了第81票
1买了第80票
1买了第79票
1买了第78票
1买了第77票
1买了第76票
1买了第75票
1买了第74票
1买了第73票
1买了第72票
1买了第71票
1买了第70票
1买了第69票
1买了第68票
1买了第67票
1买了第66票
1买了第65票
1买了第64票
1买了第63票
1买了第62票
1买了第61票
1买了第60票
1买了第59票
1买了第58票
1买了第57票
1买了第56票
1买了第55票
1买了第54票
1买了第53票
1买了第52票
1买了第51票
1买了第50票
1买了第49票
1买了第48票
1买了第47票
1买了第46票
1买了第45票
1买了第44票
1买了第43票
1买了第42票
1买了第41票
1买了第40票
1买了第39票
1买了第38票
1买了第37票
3买了第36票
3买了第35票
3买了第34票
3买了第33票
3买了第32票
3买了第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票
3买了第12票
3买了第11票
3买了第10票
3买了第9票
3买了第8票
3买了第7票
3买了第6票
3买了第5票
3买了第4票
3买了第3票
3买了第2票
3买了第1票

结果分析:

      while(true){1. 代表了3个线程都进入了 while()方法,在下面的这个方法进行排队(队列),一个一个的拿锁,进行执行。这种情况有时,会跟情况1的结果相同,但是执行的过程是不同的,下面的是由于cpu执行的过快,导致的。可以添加Thread.sleep()方法,便可以看见不同的结果。()如下synchronized (this){// 票没有了,就进行停止if(ticket <= 0){break;}//有票就进行卖票System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"票");//买了一张,就少一张票ticket--;}}
@Overridepublic  void run() {//怎么买票? 票没就结束//循环买票while(true){synchronized (this){// 票没有了,就进行停止if(ticket <= 0){break;}//有票就进行卖票System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"票");//买了一张,就少一张票ticket--;}try {Thread.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}}}

结果:

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

添加方式四:代码块(注意位置)

    //在这个方法中,进行买票@Overridepublic  void run() {//怎么买票? 票没就结束//循环买票while(true){// 票没有了,就进行停止if(ticket <= 0){break;}synchronized (this){//有票就进行卖票System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"票");//买了一张,就少一张票ticket--;}}}

结果

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

结果详解

      while(true){// 票没有了,就进行停止if(ticket <= 0){break;}可以发现,结果中有,1,0,-1 ,出问题了是吧。分析:所以线程进入了这里,发现了同步代码块,进行排队+一个一个的获取锁,然后执行。那么,当ticket==1时,而且,3个线程都进入这里了,因为判断ticket <=0 的语句是在上面。直接执行即可。所以会有这种 1,0,-1的结果。synchronized (this){//有票就进行卖票System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"票");//买了一张,就少一张票ticket--;}}

每次思考都会有收获。这次记录一下。

多线程(并发)买票的案例详解同步代码块和同步方法 (复习)相关推荐

  1. java同步方法完成案例_Java同步代码块和同步方法原理与应用案例详解

    本文实例讲述了java同步代码块和同步方法.分享给大家供大家参考,具体如下: 一 点睛 所谓原子性WOmoad:一段代码要么执行,要么不执行,不存在执行一部分被中断的情况.言外之意是这段代码就像原子一 ...

  2. java 同步块原理_Java同步代码块和同步方法原理与应用案例详解

    Java同步代码块和同步方法原理与应用案例详解 发布于 2020-8-7| 复制链接 摘记: 本文实例讲述了Java同步代码块和同步方法.分享给大家供大家参考,具体如下:一 点睛所谓原子性:一段代码要 ...

  3. 同步代码块和同步方法案例实战

    什么是同步 同步就是加锁,不让其它人访问 synchronized指的就是同步的意思 什么情况下需要同步 当多线程并发, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步, ...

  4. 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁

    什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...

  5. 多线程-并发工具类之CyclicBarrier详解

    文章目录 简介 例子 实现原理 小结 简介 从字面意思理解,CyclicBarrier是回环屏障的意思,它可以让一组线程全部达到一个状态后再全部同时执行.这里之所以叫作回环是因为当所有等待线程执行完毕 ...

  6. java中synchronized(同步代码块和同步方法)详解及区别

    问题的由来: 看到这样一个面试题: ? 1 2 3 4 5 6 //下列两个方法有什么区别 public synchronized void method1(){} public void metho ...

  7. Java多线程(含生产者消费者模式详解)

    多线程 导航 多线程 1 线程.进程.多线程概述 2 创建线程 (重点) 2.1 继承Thread类(Thread类也实现了Runnable接口) 2.2 实现Runnable接口(无消息返回) 2. ...

  8. Java20-day11【实现多线程(进程、线程-调度-控制-生命周期)、线程同步(同步代码块、线程安全、Lock)、生产者消费者(模式概述、案例)】

    视频+资料[链接:https://pan.baidu.com/s/1MdFNUADVSFf-lVw3SJRvtg   提取码:zjxs] Java基础--学习笔记(零起点打开java世界的大门)--博 ...

  9. 黑马毕向东Java课程笔记(day11):多线程(第一部分)——进程与线程+线程创建+线程安全与同步代码块+同步锁/死锁

    多线程好文:添加链接描述 锁机制:synchronized.Lock.Condition.volatile(原子性可见性)--参考添加链接描述 1.进程与线程概述   首先,对于CPU执行每一个程序, ...

最新文章

  1. 如何有效实现软件的需求管理(6)
  2. 引用类型String的操作
  3. java 接口与包_java常用类包接口
  4. 2015年度“最佳技术团队”和“最佳CTO”评选活动火热进行中
  5. 字符串:3.KMP算法(快速模式匹配算法)详解
  6. javascript中的时间处理
  7. SwitchHosts 没有权限operation not permitted解决方案
  8. 禁忌搜索算法(现代优化计算方法)
  9. 腾讯的职级系统——看清自己的职场宿命
  10. JVM源码分析之Attach机制实现完全解读
  11. Dazdata BI产品3D+BI医院综合管理应用案例
  12. ASEMI代理AD823AARZ-RL原装ADI车规级AD823AARZ-RL
  13. YTU 问题 : 排序
  14. 看《江山美人》,让我三次笑场
  15. python爬取糗事百科内容
  16. 如何设置窗口函数中窗口的大小
  17. ios开发防止App被抓包
  18. java桑硅谷 day23 晨考
  19. [CareerCup] 18.3 Randomly Generate Integers 随机生成数字
  20. OpenGL鼠标交互

热门文章

  1. Building Secure Environments for Microservices
  2. 数据库系统之函数依赖
  3. 盈透证券 简单API 实战
  4. 数据中心服务器冷却技术,数据中心高效液体冷却系统一
  5. mysql in最大长度_mysql In长度的问题?
  6. 代理记账公司如何找到精准客户
  7. 利用CyberArticle定时自动下载保存博客的新文章
  8. 原根的存在性 相关定理 (一)
  9. python 散点图颜色大全
  10. bzoj3170【TJOI2013】松鼠聚会