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

package com.yangyuanyuan.juc1205;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; class Aircondition
{
private int number = 0;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition(); public void increment()throws Exception
{
lock.lock();
try
{
//1 判断
while (number != 0)
{
condition.await();//this.wait();
}
//2 干活
number++;
System.out.println(Thread.currentThread().getName()+"\t"+number);
//3 通知
condition.signalAll();//this.notifyAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void decrement()throws Exception
{
lock.lock();
try
{
//1 判断
while (number == 0)
{
condition.await();//this.wait();
}
//2 干活
number--;
System.out.println(Thread.currentThread().getName()+"\t"+number);
//3 通知
condition.signalAll();//this.notifyAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
/*public synchronized void increment()throws Exception
{
//1 判断
while (number != 0)
{
//AAA CCC
this.wait();
}
//2 干活
number++;
System.out.println(Thread.currentThread().getName()+"\t"+number);
//3 通知
this.notifyAll();
}
public synchronized void decrement()throws Exception
{
//1 判断
while(number == 0)
{
this.wait();
}
//2 干活
number--;
System.out.println(Thread.currentThread().getName()+"\t"+number);
//3 通知
this.notifyAll();
}*/ } /**
1 高聚低合前提下,线程操作资源类
2 判断/干活/通知
3 防止虚假唤醒 不能使用if判断,会出现2 知识小总结 = 多线程编程套路+while判断+新版写法
*/
public class ProdConsumerDemo04
{
public static void main(String[] args)throws Exception
{
Aircondition aircondition = new Aircondition(); new Thread(() -> {
for (int i = 1; i <=10; i++)
{
try
{
Thread.sleep(200);
aircondition.increment();
} catch (Exception e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(() -> {
for (int i = 1; i <=10; i++)
{
try
{
Thread.sleep(300);
aircondition.decrement();
} catch (Exception e) {
e.printStackTrace();
}
}
},"B").start(); new Thread(() -> {
for (int i = 1; i <=10; i++)
{
try
{
Thread.sleep(400);
aircondition.increment();
} catch (Exception e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(() -> {
for (int i = 1; i <=10; i++)
{
try
{
Thread.sleep(500);
aircondition.decrement();
} catch (Exception e) {
e.printStackTrace();
}
}
},"D").start(); }
}

使用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. LeetCode222 判断是否为完全二叉树并求节点个数

    给出一个完全二叉树,求出该树的节点个数. 说明: 完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置.若最底 ...

  2. 了解一下ajax

    AJAX:是一种无需重新加载页面的情况下能够更新部分(局部更新)网页的技术. 1. 概念:ASychronous JavaScript And XML 异步的JavaScript和XML 首先了解一下 ...

  3. 【Azure Developer】Python代码通过AAD认证访问微软Azure密钥保管库(Azure Key Vault)中机密信息(Secret)

    关键字说明 什么是 Azure Active Directory?Azure Active Directory(Azure AD, AAD) 是 Microsoft 的基于云的标识和访问管理服务,可帮 ...

  4. Vim 自动添加脚本头部信息

    每次写脚本还在为忘记添加头部信息啥的烦恼? 按照下面这么做,帮你减轻点烦恼. # 打开配置文件: vim /root/.vimrc # 添加如下信息: autocmd BufNewFile *.sh ...

  5. os.walk() 遍历目录下的文件夹和文件

    os.walk(top, topdown=True, onerror=None, followlinks=False) top:顶级目录 os.walk()返回一个三元tupple(dirpath, ...

  6. 超详细 安装VMware Workstation,并安装WIN10操作系统连接外网 步骤指导

    首先下载VMware Workstation15.1版本,我保存在迅雷链接里面,下载速度非常可观. 链接:https://pan.xunlei.com/s/VMRSt6hHMZXEmPZCm6gJcG ...

  7. HTML5表格详细教程

    HTML5表格 文章目录 HTML5表格 5.1 定义表格 5.1.1 普通表格.列标题 5.1.2 表格标题 5.1.3 表格行分组.表格列分组 5.2 表格属性 5.2.1 单线表格.分离单元格 ...

  8. 中断与系统调用深度分析(以网络编程接口SocketAPI为例)

    1.从计算机CPU与I/O设备的交互方式谈起 计算机CPU与I/O设备的交互方式有最早的程序查询(也叫轮询)方式,发展到后来的程序中断方式,DMA方式等.简单来说,最早的程序查询方式的机制是,CPU若 ...

  9. 基于Redo Log和Undo Log的MySQL崩溃恢复流程

    在之前的文章「简单了解InnoDB底层原理」聊了一下MySQL的Buffer Pool.这里再简单提一嘴,Buffer Pool是MySQL内存结构中十分核心的一个组成,你可以先把它想象成一个黑盒子. ...

  10. eNSP启动设备AR1失败记一次解决步骤

    eNSP稳定版本下载:   微信搜索公众号"疯刘小三" 关注后回复ensp即可获得下载链接地址 eNSP V100R002C00B510 Setup.exe 最近在用eNSp的时候 ...