java八股文面试[多线程]——虚假唤醒

阻塞队列中,如果需要线程挂起操作,判断有无数据的位置采用的是while循环 ,为什么不能换成if

肯定是不能换成if逻辑判断

线程A,线程B,线程E,线程C。 其中ABE生产者,C属于消费者

put阻塞代码:

//put方法,阻塞时可中断public void put(E e) throws InterruptedException {checkNotNull(e);final ReentrantLock lock = this.lock;lock.lockInterruptibly();//该方法可中断try {//当队列元素个数与数组长度相等时,无法添加元素while (count == items.length)//将当前调用线程挂起,添加到notFull条件队列中等待唤醒notFull.await();enqueue(e);//如果队列没有满直接添加。。} finally {lock.unlock();}}

假如线程的队列是满的,会进行阻塞,待加入的元素还未执行,需要等一个空位置

// E,拿到锁资源,还没有走while判断
while (count == items.length)// A醒了// B挂起notFull.await();
enqueue(e);

C此时消费一条数据,执行notFull.signal()唤醒一个线程A线程被唤醒(A是因为等待空位置进行的阻塞)

E这时刚好需要生产一个对象,走判断,发现有空余位置(A还没有加入元素),可以添加数据到队列,E添加数据,走enqueue,这个时候队列满了。如果判断是if(notFull.await 只执行一次)A在E释放锁资源后,拿到锁资源,直接走enqueue方法。此时A线程就是在putIndex的位置,覆盖掉之前E加入的的数据,造成数据安全问题

本质原因是,在生产者从被阻塞唤醒时,其他生产者可以能已经加了一个元素,导致队列满了。

直接看while和if的区别

可以看出来,if 是true情况下,if内的代码也只会执行一次,而while直至不满足条件才能跳出while循环

先分析while情况下
public class Demo {public static void main(String[] args) {Products data = new Products();new Thread(() -> {for (int i = 0; i < 10; i++) {data.increment();}},"A1").start();new Thread(() -> {for (int i = 0; i < 10; i++) {data.decrement();}},"B1").start();new Thread(() -> {for (int i = 0; i < 10; i++) {data.increment();}},"A2").start();new Thread(() -> {for (int i = 0; i < 10; i++) {data.decrement();}},"B2").start();}
}class Products{private int number = 0;public synchronized void increment(){while (number !=0){try {System.out.println(Thread.currentThread().getName()+"商品充足,当前商品数量为"+number);System.out.println(Thread.currentThread().getName()+"wait前");this.wait();System.out.println(Thread.currentThread().getName()+"wait后");} catch (InterruptedException e) {e.printStackTrace();}}number++;System.out.println(Thread.currentThread().getName()+"数据加一 !===>" + number);this.notifyAll();}public synchronized void decrement(){while (number == 0){try {System.out.println(Thread.currentThread().getName()+"商品不足,当前商品数量为"+number);System.out.println(Thread.currentThread().getName()+"wait前");this.wait();System.out.println(Thread.currentThread().getName()+"wait后");} catch (InterruptedException e) {e.printStackTrace();}}number--;System.out.println(Thread.currentThread().getName()+"数据减一 !===>" + number);this.notifyAll();}
}

创建了两个生产者和两个消费者

可以看出来,当前线程wait后,之后就会唤醒其他线程,获取到CPU的线程后再执行wait后面一行代码,可以得出结论 wait后 该线程代码停留在此点,并释放锁,等待唤醒后就会继续执行wait后的代码 (wait是立马释放当前锁,进入阻塞状态,notify是执行完当前代码块后面的代码再释放锁)

由此可以根据if和while的特性推导

​如果是while,唤醒后,把wait后面循环体代码执行完后,会判断while是否为true,只有不满足才能跳出while

​如果是if,唤醒后,会直接顺着wait后面的代码执行下去,不会考虑if是否为true

虚假唤醒:当线程从条件变量中苏醒过来时,发现等待的条件并没有满足,该Demo产生的情况是使用if,生产者A1执行完后,唤醒其他线程,获取到的CPU却是生产者A2,A2进入if中后,并没有满足条件,但是由于是if,会顺着执行再次生产一个,消费者同理。
 

知识来源:

虚假唤醒分析_落月飞雪的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/123386.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FPGA原理与结构——FIFO IP核的使用与测试

一、前言 本文介绍FIFO Generator v13.2 IP核的具体使用与例化&#xff0c;在学习一个IP核的使用之前&#xff0c;首先需要对于IP核的具体参数和原理有一个基本的了解&#xff0c;具体可以参考&#xff1a; FPGA原理与结构——FIFO IP核原理学习https://blog.csdn.net/apple_5…

springboot web开发静态资源的映射规则

前言 我们之间介绍过SpringBoot自动配置的原理&#xff0c;基本上是如下&#xff1a; xxxxAutoConfiguration&#xff1a;帮我们给容器中自动配置组件&#xff1b; xxxxProperties:配置类来封装配置文件的内容&#xff1b; web开发中都在org.springframework.boot.autoconfig…

kubeadm搭建kubernetes(k8s)

kubeadm搭建kubernetes&#xff08;k8s&#xff09; 一、环境准备1.所有节点&#xff0c;关闭防火墙规则&#xff0c;关闭selinux&#xff0c;关闭swap交换2.修改主机名3.所有节点修改hosts文件4.调整内核参数5.生效参数 二、 安装软件1.所有节点安装docker2.所有节点安装kubea…

Java8实战-总结22

Java8实战-总结22 使用流数值流原始类型流特化数值范围数值流应用&#xff1a;勾股数 使用流 数值流 可以使用reduce方法计算流中元素的总和。例如&#xff0c;可以像下面这样计算菜单的热量&#xff1a; int calories menu.stream().map(Dish::getcalories).reduce(0, Int…

使用spring自带的发布订阅机制来实现消息发布订阅

背景 公司的项目以前代码里面有存在使用spring自带发布订阅的代码&#xff0c;因此稍微学习一下如何使用&#xff0c;并了解一下这种实现方式的优缺点。 优点 实现方便&#xff0c;代码方面基本只需要定义消息体和消费者&#xff0c;适用于小型应用程序。不依赖外部中间件&a…

msvcr120.dll放在哪里?怎么修复msvcr120.dll文件

当您在运行某些应用程序或游戏时遇到“msvcr120.dll缺失”错误时&#xff0c;这可能会影响您的使用体验。msvcr120.dll是Microsoft Visual C Redistributable的一部分&#xff0c;并且它提供了程序运行所需的运行时支持&#xff0c;今天我们来讨论一下msvcr120.dl文件缺失了要怎…

祝贺埃文科技入选河南省工业企业数据安全技术支撑单位

近日&#xff0c;河南省工业信息安全产业发展联盟公布了河南省工业信息安全应急服务支撑单位和河南省工业企业数据安全技术支撑单位遴选结果,最终评选出19家单位作为第一届河南省工业信息安全应急服务支撑单位和河南省工业企业数据安全技术支撑单位。 埃文科技凭借自身技术优势…

leetcode 20.有效括号 栈的简单应用

题目 数据结构 栈 code var isValid function(s) {// 空串和长度为奇数的字符串一定不符合要求if(!s || s.len%2){return true}let match {(: ),[: ],{: }}let stack []let len s.lengthfor(let i0; i<len; i){const ch s[i]if(ch[ || ch( || ch{){// 如果是左括号,…

2.k8s账号密码登录设置

文章目录 前言一、启动脚本二、配置账号密码登录2.1.在hadoop1&#xff0c;也就是集群主节点2.2.在master的apiserver启动文件添加一行配置2.3 绑定admin2.4 修改recommended.yaml2.5 重启dashboard2.6 登录dashboard 总结 前言 前面已经搭建好了k8s集群&#xff0c;现在设置下…

python Playwright优化页面等待和处理异步操作

在使用 Playwright 进行页面自动化时&#xff0c;优化页面等待和处理异步操作是非常重要的&#xff0c;可以提高脚本的稳定性和执行效率。 优化页面等待和处理异步操作的建议 **1. 使用正确的等待条件&#xff1a;**Playwright 提供了多种等待条件&#xff0c;如等待元素出现…

2023年9月软考高级信息系统项目管理师认证报名找弘博创新

信息系统项目管理师是全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;简称软考&#xff09;项目之一&#xff0c;是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试&#xff0c;既属于国家职业资格考试&#xff0c;又是职称资…

Excel VSTO开发8 -相关控件

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 8 相关控件 在VSTO开发中&#xff0c;Ribbon&#xff08;或称为Ribbon UI&#xff09;是指Office应用程序中的那个位于顶部的带有选…

Python实现猎人猎物优化算法(HPO)优化BP神经网络分类模型(BP神经网络分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 猎人猎物优化搜索算法(Hunter–prey optimizer, HPO)是由Naruei& Keynia于2022年提出的一种最新的…

【C++】—— 单例模式详解

前言&#xff1a; 本期&#xff0c;我将要讲解的是有关C中常见的设计模式之单例模式的相关知识&#xff01;&#xff01; 目录 &#xff08;一&#xff09;设计模式的六⼤原则 &#xff08;二&#xff09;设计模式的分类 &#xff08;三&#xff09;单例模式 1、定义 2、…

【数学建模竞赛】优化类赛题常用算法解析

优化类建模 问题理解和建模&#xff1a;首先&#xff0c;需要深入理解问题&#xff0c;并将问题抽象为数学模型。这包括确定问题的目标函数、约束条件和决策变量。 模型分析和求解方法选择&#xff1a;对建立的数学模型进行分析&#xff0c;可以使用数学工具和方法&#xff0c;…

【vue】使用无障碍工具条(详细)

引入&#xff1a;使用的是太阳湾的无障碍工具条&#xff0c;代码地址&#xff1a;https://gitee.com/tywAmblyopia/ToolsUI 具体步骤&#xff1a;下载代码后&#xff0c;将其中的 canyou 文件夹拖入 vue 项目中的 public 文件夹中&#xff1b; 上图是在项目目录中的样子&#…

【计算机视觉项目实战】中文场景识别

✨专栏介绍: 经过几个月的精心筹备,本作者推出全新系列《深入浅出OCR》专栏,对标最全OCR教程,具体章节如导图所示,将分别从OCR技术发展、方向、概念、算法、论文、数据集等各种角度展开详细介绍。 👨‍💻面向对象: 本篇前言知识主要介绍深度学习知识,全面总结知知识…

Android Ble蓝牙App(七)扫描过滤

Ble蓝牙App&#xff08;七&#xff09;扫描过滤 前言目录正文一、增加菜单二、使用MMKV① 添加依赖② 封装MMKV③ 使用MMKV 三、过滤空设备名四、过滤Mac地址五、过滤RSSI六、源码 前言 在上一篇文章中了解了MTU的相关知识以及对于设备操作信息的展示&#xff0c;本篇文章中将增…

基于SSM的校园驿站管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

Android Studio开发入门教程:如何更改APP的图标?

更改APP的图标&#xff08;安卓系统&#xff09; 环境&#xff1a;Windows10、Android Studio版本如下图、雷电模拟器。 推荐图标库 默认APP图标 将新图标拉进src/main/res/mipmap-hdpi文件夹&#xff08;一般app的icon图标是存放在mipmap打头的文件夹下的&#xff09; 更改sr…