在上一次https://www.cnblogs.com/webor2006/p/11422587.html中通过实践来解了一个案例,先来回顾一下习题:

编写一个多线程程序,实现这样的一个目标:

1、存在一个对象,该对象有一个int类型的成员变量counter,该成员变量的初始值为0。

2、创建两个线程,其中一个线程对该对象的成员变量counter增1,另一个线程对该对象的成员变量减1。

3、输出该对象成员变量counter每次变化后的值。

4、最终输出的结果应为:101010101010。。。。

具体实现的代码就不回顾了,在上次的文末提到了这么一句:

下面来验证一下这个“完美”,目前这个程序只有一个线程去增,另一个线程去减,那。。如果对于增和减对应多个线程又会如何呢?下面改造一下:

看下结果是否依然如预期:

很明显一开始输出就不对了,另外!!

那。。为啥呢?两个线程就妥妥的,升级一下线程数就出问题,其实在以前https://www.cnblogs.com/webor2006/p/8419565.html的这篇博文中也专门学习过,这里再回忆捋一下:

现有是有两个增加线程和两个减少线程,假如目前有一个增加线程执行了增加方法,此时的counter++=1,如下:

接着用来减少的线程执行减少操作了,由于counter目前是1,所以可以正常执行到减操作,所以counter--=0:

好,第三个线程还是减少的线程又来执行减少操作了,而由于此时的counter=0,所以这个减少线程会进行wait(),如下:

接着还剩的一个减少线程又来执行减少操作了,此时由于counter还是等于0,那。。由于wait()是会将当前对象的锁给释放的,所有减小的两个线程此时都处于wait()状态了。

好接下来增加的一个线程来了,执行增加操作,由于减少的两个线程都处于wait()状态都不会持有对象的锁了,所以这个增加线程肯定是能正常执行增加操作的,目前count就会由0变为1了,如下:

接着注意重点来了:

好,正在wait()的两个减少的线程其中一个被唤醒了,所以接下来该线程就会将count--=0,如下:

好,重点又来了:

那么,最后一个wait()的减小线程又执行了一次counter--=-1:

所以结果就已经出问题了,其中需要特别注意的是:

也就是说:

回归到这个程序的问题上来,其实本质是由于:

所以,咱们来改一下程序:

好,咱们再运行一下:

一切正常了,而且可以看到程序也正常可以退出来。这也如官方文档所说:

其中还有一个原因需要注意:“spurious wakeups”,假唤醒,如果不放循环中肯定也会出问题。

最新文章

  1. odi 12.2.1.1新特性
  2. golang: 根据json生成go源文件
  3. proteus怎么仿真?
  4. PHOG特征
  5. Mysql学习笔记(一)
  6. ubuntu 16.04 apt-get error: in the drive /media/cdrom and press
  7. js json与对象的相互转换
  8. LA 4384
  9. Java Socket实战之一 单线程通信
  10. Javascript自执行匿名函数(function() { })()的原理浅析
  11. xhEditor与Java结合使用
  12. clipboard让复制的文本换行
  13. 见过NTP服务,没见过网络流量到200M左右的NTP服务
  14. mac下和windows下清空DNS缓存
  15. 强化学习读书笔记 - 02 - 多臂老O虎O机问题
  16. 使用JS开发桌面端应用程序NW.js-2-开发问题小记
  17. Struts2学习笔记二 配置详解
  18. Y7000安装驱动显卡问题
  19. Spring日记_02之搭建一个新项目
  20. 2018-2019-2 20175211 实验一《Java开发环境的熟悉》实验报告

热门文章

  1. GitLab - GitLab的备份与还原
  2. 「模拟赛20191019」A 简单DP
  3. linux中安装python3.7
  4. LeetCode 2. 两数相加(Add Two Numbers)
  5. [转帖]keepalived实现服务高可用
  6. python学习-61 类
  7. PB 计算公式算出结果赋值给另外一列
  8. 数据建模工具------EZMNL
  9. 作为一个纯粹数据结构的 Redis Streams
  10. python多线程一些知识点梳理