现在两个线程,可以操作初始值为零的一个变量,实现一个线程对该变量加1,一个线程对该变量减1,实现交替,来10轮,变量初始值为零。

  1. package com.yangyuanyuan.juc1205;
  2.  
  3. import java.util.concurrent.locks.Condition;
  4. import java.util.concurrent.locks.Lock;
  5. import java.util.concurrent.locks.ReentrantLock;
  6.  
  7. class Aircondition
  8. {
  9. private int number = 0;
  10. private Lock lock = new ReentrantLock();
  11. private Condition condition = lock.newCondition();
  12.  
  13. public void increment()throws Exception
  14. {
  15. lock.lock();
  16. try
  17. {
  18. //1 判断
  19. while (number != 0)
  20. {
  21. condition.await();//this.wait();
  22. }
  23. //2 干活
  24. number++;
  25. System.out.println(Thread.currentThread().getName()+"\t"+number);
  26. //3 通知
  27. condition.signalAll();//this.notifyAll();
  28. }catch (Exception e){
  29. e.printStackTrace();
  30. }finally {
  31. lock.unlock();
  32. }
  33. }
  34. public void decrement()throws Exception
  35. {
  36. lock.lock();
  37. try
  38. {
  39. //1 判断
  40. while (number == 0)
  41. {
  42. condition.await();//this.wait();
  43. }
  44. //2 干活
  45. number--;
  46. System.out.println(Thread.currentThread().getName()+"\t"+number);
  47. //3 通知
  48. condition.signalAll();//this.notifyAll();
  49. }catch (Exception e){
  50. e.printStackTrace();
  51. }finally {
  52. lock.unlock();
  53. }
  54. }
  55. /*public synchronized void increment()throws Exception
  56. {
  57. //1 判断
  58. while (number != 0)
  59. {
  60. //AAA CCC
  61. this.wait();
  62. }
  63. //2 干活
  64. number++;
  65. System.out.println(Thread.currentThread().getName()+"\t"+number);
  66. //3 通知
  67. this.notifyAll();
  68. }
  69. public synchronized void decrement()throws Exception
  70. {
  71. //1 判断
  72. while(number == 0)
  73. {
  74. this.wait();
  75. }
  76. //2 干活
  77. number--;
  78. System.out.println(Thread.currentThread().getName()+"\t"+number);
  79. //3 通知
  80. this.notifyAll();
  81. }*/
  82.  
  83. }
  84.  
  85. /**
  86. 1 高聚低合前提下,线程操作资源类
  87. 2 判断/干活/通知
  88. 3 防止虚假唤醒 不能使用if判断,会出现2
  89.  
  90. 知识小总结 = 多线程编程套路+while判断+新版写法
  91. */
  92. public class ProdConsumerDemo04
  93. {
  94. public static void main(String[] args)throws Exception
  95. {
  96. Aircondition aircondition = new Aircondition();
  97.  
  98. new Thread(() -> {
  99. for (int i = 1; i <=10; i++)
  100. {
  101. try
  102. {
  103. Thread.sleep(200);
  104. aircondition.increment();
  105. } catch (Exception e) {
  106. e.printStackTrace();
  107. }
  108. }
  109. },"A").start();
  110. new Thread(() -> {
  111. for (int i = 1; i <=10; i++)
  112. {
  113. try
  114. {
  115. Thread.sleep(300);
  116. aircondition.decrement();
  117. } catch (Exception e) {
  118. e.printStackTrace();
  119. }
  120. }
  121. },"B").start();
  122.  
  123. new Thread(() -> {
  124. for (int i = 1; i <=10; i++)
  125. {
  126. try
  127. {
  128. Thread.sleep(400);
  129. aircondition.increment();
  130. } catch (Exception e) {
  131. e.printStackTrace();
  132. }
  133. }
  134. },"C").start();
  135. new Thread(() -> {
  136. for (int i = 1; i <=10; i++)
  137. {
  138. try
  139. {
  140. Thread.sleep(500);
  141. aircondition.decrement();
  142. } catch (Exception e) {
  143. e.printStackTrace();
  144. }
  145. }
  146. },"D").start();
  147.  
  148. }
  149. }

使用if判断存在虚假唤醒情况,变量可能会变成2

如图所示,如果只有两个线程,一个线程加,一个线程减,不会存在虚假唤醒情况(选无可选)。

当变成四个线程时,两个线程加,两个线程减,使用if就会存在虚假唤醒情况。如变量初始为0(0!=0为false),执行完+’变量变成1,此时+线程进来发现值为1等待(this.wait()处等待,未出if判断),然后+‘线程又进来发现值为1它也等待(this.wait()处等待,未出if判断),此时-线程进来(1==0为false)发现变量值为1将变量做减法变成0。由于此时+和+‘仍在等待,cpu为了降低消耗量和负担,会先满足等待时间长的线程(线程优先级会高)

由于使用的是if,不会再拉回来重新判断一次(两个线程this.wait()处等待),+和+’线程都会做加法,变量值就变成了2。

Java多线程操作同一份资源的更多相关文章

  1. Java多线程操作同一个对象,线程不安全

    Java多线程操作同一个对象 发现问题:多个线程操作同一资源的情况下,线程不安全,数据紊乱 代码: package multithreading; // Java多线程操作同一个对象 // 买火车票的 ...

  2. java多线程操作

    进程是程序的一次动态的执行过程,它经历了从代码加载.执行完毕的一个完整过程,这个过程也是进程本身从产生.发展到最终消亡的过程. 多线程是实现并发机制的一种有效的手段.进程和线程一样,都是实现并发的一个 ...

  3. java多线程(五)-访问共享资源以及加锁机制(synchronized,lock,voliate)

    对于单线程的顺序编程而言,每次只做一件事情,其享有的资源不会产生什么冲突,但是对于多线程编程,这就是一个重要问题了,比如打印机的打印工作,如果两个线程都同时进行打印工作,那这就会产生混乱了.再比如说, ...

  4. 【转】Java多线程操作局部变量与全局变量

    原文网址:http://blog.csdn.net/undoner/article/details/12849661 在这篇文章里,我们首先阐述什么是同步,不同步有什么问题,然后讨论可以采取哪些措施控 ...

  5. Java多线程操作局部变量与全局变量

    在这篇文章里,我们首先阐述什么是同步,不同步有什么问题,然后讨论可以采取哪些措施控制同步,接下来我们会仿照回顾网络通信时那样,构建一个服务器端的"线程池",JDK为我们提供了一个很 ...

  6. java 多线程操作List,已经做了同步synchronized,还会有ConcurrentModificationException,知道为什么吗?

    如题,最近项目里有个模块我做了异步处理方面的事情,在code过程中发现一个颠覆我对synchronized这个关键字和用法的地方,请问各位java开发者们是否对此有一个合理的解释,不多说,我直接贴出问 ...

  7. java 多线程操作(锁)

    1.对象的加锁及其操作 程序中单独的并发线程对同一对象进行操作的代码段,成为临界区.java语言中的临界区可以是一个语句块 或者方法,使用关键字synchronized进行标识. 对象锁:java平台 ...

  8. Java 多线程(一)—— 概念的引入

      并发和并行 并行:指两个或多个时间在同一时刻发生(同时发生): 并发:指两个或多个事件在一个时间段内发生. 在操作系统中,安装了多个程序,并发指的是在一段时间内宏观上有多个程序同时运行,这在单 C ...

  9. java多线程(2) 线程同步

    我们对线程访问同一份资源的多个线程之间,来进行协调的这个东西,就是线程同步.   例子1:模拟了多个线程操作同一份资源,可能带来的问题: package com.cy.thread; public c ...

随机推荐

  1. MySql中的有条件插入 insert where

    假设现在我们有这样的需求:当数据库中不存在满足条件的记录时,可以插入一条记录,否则程序退出.该怎么实现? 1年以上工作经验的人应该都能立即想到:去检查一下库里有没有记录,没有就插入,有就结束. int ...

  2. Spring的自动装配与依赖注入

    Spring的自动装配与依赖注入 装配 = 创建Bean + 注入Bean 创建Bean 自动发现 显式注册Bean 注入Bean 基于配置的注入 自动注入 Spring的装配分为显式装配和隐式装配, ...

  3. 关于vuex的数据不直接给data而要通过computed

    # 为什么vuex的数据不直接给data而要通过computed计算 ## 疑惑 其实一直以来使用vue的状态管理vuex都有一个疑惑,文档中介绍,vue的状态数据`$store.state.xx`的 ...

  4. 剑指Offer58-左转字符串

    题目 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S=" ...

  5. LeetCode141-环形链表检测

    题目 给定一个链表,判断链表中是否有环. 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置 ...

  6. 【Java集合】HashSet源码解析以及HashSet与HashMap的区别

    HashSet 前言 HashSet是一个不可重复且元素无序的集合.内部使用HashMap实现. 我们可以从HashSet源码的类注释中获取到如下信息: 底层基于HashMap实现,所以迭代过程中不能 ...

  7. Nginx 实现动态负载均衡(Nginx-1.10.1 + Consul v0.6.4)

    一直也没有找到合适的类似Socat + Haproxy 的组合能用在Nginx,后来发现了Nginx的几个模块,但是也存在各种不足. 而且Nginx 在大流量的情况下nginx -s reload 是 ...

  8. windows鼠标右键添加快捷方式

    [win]+[R] 输入regedit 打开路径:计算机\HKEY_CLASSES_ROOT\DesktopBackground\Shell 创建应用文件,这里以putty为例 右键 Shell 新建 ...

  9. 在 WPF 中使用 MahApps.Metro.IconPacks 提供的大量图标

    MahApps.Metro.IconPacks https://github.com/MahApps/MahApps.Metro.IconPacks 提供了大量的高质量的图标供WPF使用,极其方便. ...

  10. Spring源码深度解析之事务

    Spring源码深度解析之事务 目录 一.JDBC方式下的事务使用示例 (1)创建数据表结构 (2)创建对应数据表的PO (3)创建表和实体之间的映射 (4)创建数据操作接口 (5)创建数据操作接口实 ...