【Java】volatile-内存可见性问题

1、什么是内存可见性问题?

(1)实例

要明白什么是内存可见性,我们首先来看一段代码

public class demo1 {public static int isQuit = 0;public static void main(String[] args) {Thread thread1 = new Thread(()->{while (isQuit == 0){}System.out.println("t1线程结束");});thread1.start();Thread thread2 = new Thread(()->{Scanner scanner = new Scanner(System.in);isQuit = scanner.nextInt();System.out.println("isQuit已被修改");});thread2.start();}
}

运行结果如下

打开jconsole,查看thread1状态,发现thread1还在运行状态,也就是说thread1中的while循环还一直在继续

为什么会这样呢?

(2)内存可见性问题 

在计算机中,CPU在读取寄存器时比读取内存时快很多,这时编译器会对代码进行自动优化

在上述代码中,由于while循环中没有代码,线程1不断地读取isQuit的值进行判断,操作过于频繁

因此,编译器在第一次读取isQuit的值后,便将其存放在寄存器中,后续不再读取

导致我们在线程2里对isQuit 的值进行了修改,线程1也不能察觉

由此便产生了内存可见性问题

2、volatile

要解决内存可见性问题,我们首先想到的是使用Java中的关键字volatile

在变量前加上关键字volatile修饰,变量便不会再被编译器优化,进而就不会产生内存可见性问题

public volatile static int isQuit = 0;

完整代码如下

import java.util.Scanner;public class demo2 {public volatile static int isQuit = 0;public static void main(String[] args) {Thread thread1 = new Thread(()->{while (isQuit == 0){}System.out.println("t1线程结束");});thread1.start();Thread thread2 = new Thread(()->{Scanner scanner = new Scanner(System.in);isQuit = scanner.nextInt();System.out.println("isQuit已被修改");});thread2.start();}
}

最终运行结果

可见,内存可见性问题可用volatile关键字来解决

3、其他解决办法

 之所以产生内存可见性问题,是由于读取操作太过于频繁。只要我们降低读取的频率,同样也可以解决内存可见性问题

如在线程1中的while循环中加上sleep操作

import java.util.Scanner;public class demo3 {public static int isQuit = 0;public static void main(String[] args) {Thread thread1 = new Thread(()->{while (isQuit == 0){try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}System.out.println("t1线程结束");});thread1.start();Thread thread2 = new Thread(()->{Scanner scanner = new Scanner(System.in);isQuit = scanner.nextInt();System.out.println("isQuit已被修改");});thread2.start();}
}

运行结果

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

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

相关文章

Redis高级特性和应用(发布 订阅、Stream)

目录 发布和订阅 操作命令 发布消息 订阅消息 查询订阅情况 查看活跃的频道 查看频道订阅数 使用场景和缺点 Redis Stream Stream总述 常用操作命令 生产端 消费端 单消费者 消费组 创建消费组 消息消费 在Redis中实现消息队列 基于pub/sub 基于Stream Re…

Element Plus框架快速上手详解(一)

Element Plus框架快速上手详解 1、Element Plus1.1、安装 2、Button3、Link链接4、Layout布局5、Container布局容器6、Radio单选框6.1、单选框组6.2、事件 7、Checkbox多选框7.1、多选框组7.2、事件 8、Input输入框组件8.1、事件8.2、方法 9、Select选择器9.1、基础多选9.2、事…

pytho你-opencv划痕检测

pytho你-opencv划痕检测 这次实验,我们将对如下图片进行划痕检测,其实这个比较有难度,因为清晰度太差了。 我们做法如下: (1)读取图像为灰度图像,进行自适应直方图均衡化处理,增强…

ClickHouse的 MaterializeMySQL引擎

1 概述 MySQL 的用户群体很大,为了能够增强数据的实时性,很多解决方案会利用 binlog 将数据写入到 ClickHouse。为了能够监听 binlog 事件,我们需要用到类似 canal 这样的第三方中间件,这无疑增加了系统的复杂度。 ClickHouse 20.…

python爬虫SHA案例:某直播大数据分析平台

声明: 该文章为学习使用,严禁用于商业用途和非法用途,违者后果自负,由此产生的一切后果均与作者无关 一、找出需要加密的参数 js运行 atob(‘aHR0cDovL3d3dy5oaDEwMjQuY29tLyMvc2VhcmNoL3NlYXJjaA’) 拿到网址,F12打…

基于安卓android微信小程序的个人管理小程序

运行环境 开发语言:Java 框架:ssm JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7(一定要5.7版本) 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包&a…

记录一次较为完整的Jenkins发布流程

文章目录 1. Jenkins安装1.1 Jenkins Docker安装1.2 Jenkins apt-get install安装 2. 关联github/gitee服务与webhook2.1 配置ssh2.2 Jenkins关联2.3 WebHook 3. 前后端关联发布 1. Jenkins安装 1.1 Jenkins Docker安装 Docker很好,但是我没有玩明白如何使用Docke…

EI论文程序:Adaboost-BP神经网络的回归预测算法,可作为深度学习对比预测模型,丰富实验内容,自带数据集,直接运行!

适用平台:Matlab 2021及以上 本程序参考中文EI期刊《基于Adaboost的BP神经网络改进算法在短期风速预测中的应用》,程序注释清晰,干货满满,下面对文章和程序做简要介绍。 为了提高短期风速预测的准确性,论文提出了使用…

创新工具 | 教你6步用故事板设计用户体验事半功倍

问题 构思方案时团队在细节上难以共识 故事板是什么?故事板就像连环画一样,将用户使用解决方案的关键步骤顺序串联了起来,呈现了方案和用户之间的交互。 故事板以先后顺序展现团队票选出来的最佳解决方案,在过程中对于方案中未…

LangChain 5易速鲜花内部问答系统

展示了一个完整的问答系统的实现,使用了Flask来构建Web界面、langchain进行文档处理和检索,以及OpenAI的语言模型。代码的复杂性在于集成了多种高级技术和处理大型数据集和语言模型。 LangChain 实现给动物取名字,LangChain 2模块化prompt t…

MATLAB Simulink和S7-1200PLC MOBUSTCP通信

MATLAB Simulink和SMART PLC OPC通信详细配置请查看下面文章链接: MATLAB和西门子SMART PLC OPC通信-CSDN博客文章浏览阅读749次,点赞26次,收藏2次。西门子S7-200SMART PLC OPC软件的下载和使用,请查看下面文章Smart 200PLC PC Access SMART OPC通信_基于pc access smart的…

Django实战:从零到一构建安全高效的Web应用

目录 一、概述 二、版本控制和部署 1、Git版本控制 2、Docker部署 三、数据库配置 1、配置数据库设置 2、创建数据库模型 四、URL路由和视图 1、定义URL路由 2、创建视图 五、模板渲染 1、创建模板 2、在视图中使用模板 总结 一、概述 Django是一个高级Python W…

CleanMyMac X4.16免费版mac电脑一键清理电脑垃圾工具

但是,我最近发现随着使用时间的增加,一些奇奇怪怪的文件开始占据有限的磁盘空间,存储空间变得越来越小,系统占用空间越来越大,越来越多的无效文件开始影响我电脑的运行速度。 Mac的文件管理方式和Windows不太一样&…

基于C#实现字符串相似度

一、概念 对于两个字符串 A 和 B,通过基本的增删改将字符串 A 改成 B,或者将 B 改成 A,在改变的过程中我们使用的最少步骤称之为“编辑距离”。比如如下的字符串:我们通过种种操作,痉挛之后编辑距离为 3,不…

【zabbix监控四】zabbix之监控tomcat服务报警

一、监控tomcat服务是否正常运行 1、客户端部署 首先要在zabbix-agent客户端上安装tomcat服务,并能正常启动和关闭 1.1 客户端编写脚本 vim /opt/tomcat.sh#!/bin/bash anetstat -natp |grep 8080|awk {print $6}|grep LISTEN if [[ $a LISTEN ]];thenecho &qu…

upload-labs(1-17关攻略详解)

upload-labs pass-1 上传一个php文件,发现不行 但是这回显是个前端显示,直接禁用js然后上传 f12禁用 再次上传,成功 右键打开该图像 即为位置,使用蚁剑连接 连接成功 pass-2 源码 $is_upload false; $msg null; if (isse…

QMenuBar和QToolBar使用同一个QAction

文章目录 前言一、编辑QMenuBar二、将QMenuBar中的Action添加到toolbar总结 前言 qmenubar中的action添加到toolbar,不是在toolbar中再添加action,效果图如下 一、编辑QMenuBar 正常编辑QMenuBar,以下图为例 二、将QMenuBar中的Action添…

matlab层次分析法模型及相关语言基础

发现更多计算机知识,欢迎访问Cr不是铬的个人网站 代码放在最后面! 这篇文章是学习层次分析法模型的笔记。 1.什么时候用层次分析法 层次分析法是建模比赛中最基础的模型之一,其主要用于解决评价类问题(例如:选择哪种方案最好、…

opencv(5): 滤波器

滤波的作用:一幅图像通过滤波器得到另一幅图像;其中滤波器又称为卷积核,滤波的过程称为卷积。 锐化:边缘变清晰 低通滤波(Low-pass Filtering): 目标:去除图像中的高频成分&#…

什么是RS485通信

RS-485是一种通讯接口标准,RS就是Recommended Standard的缩写(推荐标准的意思)485是标识号。 RS485采用总线的接线方式,广泛应用于数据采集和控制,它的主要优点之一是它允许将多个RS485设备放在同一条总线上。 多设备…