共享变量可见性问题以及解决方案

文章目录

    • 1. 简介
    • 2. 解决方案

1. 简介

首先在了解可见性问题之前我们首先需要给出Java 内存模型的定义(JMM),java讲内存模型抽象为两个部分,主存以及工作内存,主 存也就是所有线程所共享的一段存储空间,工作内存是所有线程各种私有的一块内存空间,若此时某个线程想操作一个共享变量,它需要先将主存主的共享变量读取到自己的工作内存中,然后进行操作。此时就出现了一个问题,一个线程将对自己的更新推送至主存后,其它线程没有及时读取主存中共享变量的更新,而是一直使用自己工作内存中缓存的旧值,最后导致更新不可见,这就是所谓的可见性问题。看下面一段代码:

@Slf4j
public class Hello{
	//共享变量
	static  boolean flag=false;
	public static void main(String[] args) throws InterruptedException {
	  new Thread(()->{
		  while(!flag)
		  {
			  log.info("我还在等地flag等于true");
		  }
	  }).start();
	  Thread.sleep(1000);
      flag=true;
	}
}

在这里插入图片描述
最后我们创建的线程会陷入死循环,按照正常的逻辑去理解,在主线程修改flag后创建的线程会从主存空间读取到主线程的修改然后退出while循环,而出现这种结果的原因是jvm中JIT的存在,JIT即java即时编译技术,它底层又c1和c2两个编译器组成(新版本可能是c1和Graal),c2或Graal会利用一些技术对我们的代码进行优化(这会导致一些问题)。再分析一下上面代码工作的底层流程:

  1. 初始状态,t线程刚开始从主内存中读取了flag的值到工作内存中
    在这里插入图片描述
  2. 每一次新的while循环,t线程都要从主内存中读取flag的值,这是一个十分耗时的过程,所以JIT这里就对我们代码进行了优化,JIT会将flag的缓存至线程自己的工作内存中的高速缓存中,减少对flag的主存访问,提高程序运行效率。

在这里插入图片描述
3. 主线程更新flag时,main线程将对flag的更新更新到主存中的共享变量,而t线程还是使用自己缓存中的旧值。

在这里插入图片描述
最后就导致了可见性问题。

2. 解决方案

java为我们提供了volatilo关键字,volatile是一个特征修饰符(type specifier).volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值(线程不会在缓存汇中读值)。下面查看更新后的代码:

@Slf4j
public class Hello{
	//共享变量
	volatile static  boolean flag=false;
	public static void main(String[] args) throws InterruptedException {
	  new Thread(()->{
		  while(!flag)
		  {
			  log.info("我还在等地flag等于true");
		  }
	  }).start();
	  Thread.sleep(1000);
      flag=true;
	}
}

在这里插入图片描述

这就解决了可见性问题,synchronized同样也可以解决可见性,但解决可见性还是推荐使用volatile,因为synchronized是重量级锁,消耗是很大的。但相比于volatile,sychronized也有其优势,sychronized语句块既可以保证代码的原子性,也同时可以保证代码块内变量的可见性。volatile是不能保证代码的原子性,它只能保证代码我们每次读到volatile修饰的共享变量值时,都是最新的值。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Netty--NIO(Non-blocking IO)基础--三大组件

NIO(Non-blocking IO)是一种非阻塞的IO模型,它通过引入Channel和Selector的概念,使得一个线程能够管理多个通道,从而提高了IO操作的效率。本文将介绍NIO的三大组件:Channel、Buffer、以及Selector&#xff…

GEE:遥感影像二值化

作者:CSDN @ _养乐多_ 在Google Earth Engine(GEE)中,图像二值化是将图像中的像素值转换为二进制(0或1)的过程。这通常用于将连续的遥感图像转换为只有两个值的二值图像,以突出图像中的特定特征或区域。 结果如下图所示,将NDVI图像中,大于0.3的值设置为1(黑色),小…

SQL 算数函数

AVG() 求数值列的平均值。 具体计算过程:其通过对表中行数计数并计算特定数值列的列值之和,求得该列的平均值。 语法: SELECT AVG(column_name) FROM table_name; 当参数 column_name 列中的数据均为空时,结果会返回 NULL。 …

Ubuntu(WSL2) mysql8.0.31 源码安装

要在 Ubuntu 上使用调试功能安装 MySQL 8.0 的源码,可以按照以下详细步骤进行操作: 1. 更新系统 首先,确保你的 Ubuntu 系统是最新的。运行以下命令更新系统软件包: sudo apt update sudo apt upgrade 2. 下载 MySQL 源码 访…

【ATTCK】MITRE Caldera -引导规划器

一、Caldera 概念 在详细介绍新的引导式规划器之前,我们先回顾一下与 Caldera 相关的概念的一些定义。 能力是 Caldera 可以执行的最小原子动作。对手由一组能力组成。例如,旨在发现和泄露感兴趣的文件的对手可能具有发现文件、创建暂存目录、将发现的文…

Visual Studio 2019下编译OpenCV 4.7 与OpenCV 4.7 contrib

一、环境 使用的环境是Win10,Visual Studio 2019,Cmake3.28,cdua 11.7,cudnn 8.5,如果只是在CPU环境下使用,则不用安装CUDA。要使用GPU处理,安装好CUDA之后,要测试安装的CUDA是否能用。不能正常使用的话,添加一下系统…

基于vue的cron表达式组件——vue-crontab插件

前言: vue 的 cron 组件,支持解析/反解析 cron 表达式,生成最近五次的符合条件时间,依赖 vue2 和 element-ui 效果图: 一、下载安装依赖插件 npm install vcrontab 二、引用方式 //全局引入 import vcrontab f…

CKA认证模块②-K8S企业运维和落地实战

CKA认证模块②-K8S企业运维和落地实战 Pod高级实战-Pod生命周期-启动钩子,停止钩子 Pod生命周期完整流程介绍 容器钩子; 容器探测; Pod重启策略; Pod的终止过程; Init容器; 初始化容器最佳实践 初始化容器与主容器区别是? init容器没有readinessProbe… [rootk8s-mast…

python实现炒股自动化,个人账户无门槛量化交易的开始

本篇作为系列教程的引子,对股票量化程序化自动交易感兴趣的朋友可以关注我,现在只是个粗略计划,后续会根据需要重新调整,并陆续添加内容。 股票量化程序化自动交易接口 很多人在找股票个人账户实现程序化自动交易的接口&#xff0…

Java_继承和多态

文章目录 前言继承继承语法继承总结super指定访问父级子类构造方法super和this再谈初始化(执行顺序)protected 关键字继承方式final 关键字继承与组合 多态动态绑定与静态绑定多态实现条件重写 前言 适合复习看 继承 继承语法 修饰符 class 子类 extends 父类 { // ... }子类…

配置cuda和cudnn出现 libcudnn.so.8 is not a symbolic link问题

cuda版本为11.2 问题如图所示: 解决办法: sudo ln -sf /usr/local/cuda-11.2/targets/x86_64-linux/lib/libcudnn_adv_train.so.8.1.1 /usr/local/cuda-11.2/targets/x86_64-linux/lib/libcudnn_adv_train.so.8 sudo ln -sf /usr/local/cuda-11.2/targ…

Mac安装配置Tomcat,以及使用(详解)

目录 一、Tomcat下载: 1、左栏选择Tomcat版本 2、点击下载即可,任选其一 ​编辑3、下载好的文件夹放到用户名下即可(之前已经下载过,这里以Tomcat 8.5.88为演示),这里提供8.5.88的安装包: 二…

毅速丨金属3D打印零件品质受哪些因素影响

金属3D打印的零件品质受到多个因素的影响,包括设备、材料、工艺、后处理等。不同厂商的品质差别大致由以下几个方面造成。 一、设备性能差异: 不同厂商的金属3D打印设备可能存在性能上的差异,包括激光功率、扫描速度、打印精度、稳定性等。这…

istio流量管理

流量管理 目录 文章目录 流量管理目录流量管理概述请求路由1.路由到版本1🚩 实战:路由到版本1-2023.11.11(测试成功) 2.基于用户身份的路由🚩 实战:基于用户身份的路由-2023.11.11(测试成功) 关于我最后 流量管理概述 上面我们了…

跨镜头目标融合__追踪之目标重识别研究(跨镜头目标追踪)

文章目录 标题:跨镜头目标融合;目标重识别;跨镜头目标追踪; 1 目的:2 实现方法/策略:2.1 目标类型位置匹配(或考虑结合目标轨迹)2.2 目标重识别2.3 目标类型位置匹配(轨迹)目标重识别…

LeetCode【701】二叉搜索数的插入操作

题目: 思路: https://zhuanlan.zhihu.com/p/272781596 代码: class Solution {public TreeNode insertIntoBST(TreeNode root, int val) {return process(root,val); }//递归public TreeNode process(TreeNode root,int val){//base ca…

Hls学习(一)

1:CPU、DSP、GPU都算软件可编程的硬件 2:dsp在递归方面有所减弱,在递归方面有所增强,比如递归啊等,GPU可以同时处理多个进程,对于大块数据,流处理比较适用 3:为了提高运算量处理更多…

可视化 | 3D文字球状标签云

文章目录 📚改编点📚final 改编自echarts 3d词云(指向滑动、拖动、缩放、点击、自转 ) 📚改编点 背景透明:background:rgb(0,0,0,0);不用链接,用span,重点span标class"star&q…

文心耀乌镇,“大模型之光”展现了什么?

“乌镇的小桥流水,能照见全球科技的风起云涌。” 多年以来,伴随着中国科技的腾飞,以及世界互联网大会乌镇峰会的连续成功举办,这句话已经成为全球科技产业的共识。乌镇是科技与互联网的风向标、晴雨表,也是无数新故事开…

【ATTCK】MITRE Caldera 简介

一、什么是Caldera caldera是一个基于MITRE ATT&CK™构建的网络安全框架。其目标是创建一种工具,通过提供自动化安全评估来增强网络从业者的能力,从而节省用户的时间、金钱和精力。为此,需要几个关键组件才能使 Caldera 成为行业领先的平…