浅谈volatile
volatile有三个特性:
(1)可见性
(2)不保证原子性
(3)禁止指令重排
下面我们一一介绍
(一)可见性
volatile的可见性是说共享变量只要修改,就可以被其他线程感知到,这个是怎么做到的呢?
这得从虚拟机的内存模型说起,这里直接引用《深入理解java虚拟机》书中原话:JAVA内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存保存了被该线程使用的变量的主内存副本,线程对变量的所有操作(读取、赋值)都必须在工作内存中进行,而不是直接读写主内存中的数据。
所以对于多线程场景的共享变量值的传递是需要通过主内存进行。也就是线程A对共享变量tmp(没有使用volatile)修改后,线程B不一定能马上感知到。需要等线程A中的工作内存同步到主内存中,线程B才能感知到。而volatile则会保证变量只要修改就会马上同步到主内存中,并且线程读取变量时也是会先从主内存中刷新变量值,以此来保证了变量的可见性。
(二)不保证原子性
对于volatile变量,虽然线程能马上看见它的值改变,并不能保证它的运算操作是原子的,比如:
public class TestVolatile {public static volatile int count = 0;public static CountDownLatch countDownLatch = new CountDownLatch(5);public static void main(String[] args) {for (int i = 0; i < 5; i++) {new Thread(() -> {for (int j = 0; j < 10000; j++) {count++;}countDownLatch.countDown();}).start();}try {countDownLatch.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("count:" + count);}
}
上面这个例子执行后,如果是原子性的,那么count的值应该是50000。但实际远小于50000
因为i++本身就不是原子步骤,它实际上是i=i+1.它需要先获取i的值,然后再加1,然后再赋值给i。两个线程A,B同时获取i的值为3,然后线程A将其加1后的值4赋值给主内存。线程B这时也完成了计算同样赋值给主内存也是4。这是计算结果就少了1。
(3)禁止指令重排
指令重排是编译器在运行时在保证单个线程内结果不变的情况下,基于性能优化考虑对指令进行重新排序
这个先举个例子:
public static boolean initFlag = false;public static void main(String[] args) {new Thread(() -> {// 初始化完成后再设置标志位,另一个线程感知到标志位改变后,开始执行它的业务doSomeInit();initFlag = true;}).start();new Thread(() -> {while (!initFlag) {// 还没初始化则等待try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}// 认为初始化已经完成,执行它的业务}).start();}
上面这段代码并不能实际运行出我们想要的效果(因为指令重排是虚拟机编译器内部逻辑,没想到一个确实可行的例子能够触发指令重排),只是简单代替我们经常可能会出现的业务场景,一个线程等待另一个线程完成初始化逻辑后,才开始启动自己的业务逻辑。上面initFlag没有标识volatile。那么initFlag赋值操作可能会因为指令重排,先于doSomeInit初始化逻辑先完成,这样就可能导致我们的业务功能有问题。因为对于单个线程来说,虚拟机认为initFlag提前执行并没有改变所在线程的结果。所以这里需要给initFlag加上volatile标识,告诉虚拟机,这里不能进行指令重排,在initFlag操作之前的代码,也必须先于initFlag操作之前执行
相关文章:

浅谈volatile
volatile有三个特性: (1)可见性 (2)不保证原子性 (3)禁止指令重排 下面我们一一介绍 (一)可见性 volatile的可见性是说共享变量只要修改,就可以被其他线…...

Python3 爬虫 Scrapy的使用
安装完成Scrapy以后,可以使用Scrapy自带的命令来创建一个工程模板。 一、创建项目 使用Scrapy创建工程的命令为: scrapy startproject <工程名> 例如,创建一个抓取百度的Scrapy项目,可以将命令写为: scrapy s…...

多线程篇-4--重点概念1(volatile,Synchronized,内存屏障,MESI协议)
一、volatile (1)、简述 volatile是java提供的一个关键字,英文意思为不稳定的。 可以保障被声明对象的可见性和一定程度上的有序性,但不能保证操作的原子性。 当一个变量被声明为volatile时,意味着该变量的值会直接从…...

本地学习axios源码-如何在本地打印axios里面的信息
1. 下载axios到本地 git clone https://github.com/axios/axios.git 2. 下载react项目, 用vite按照提示命令配置一下vite react ts项目 npm create vite my-vue-app --template react 3. 下载koa, 搭建一个axios请求地址的服务端 a.初始化package.json mkdir koa-server…...
1、SpringBoo中Mybatis多数据源动态切换
我们以一个实例来详细说明一下如何在SpringBoot中动态切换MyBatis的数据源。 一、需求 1、用户可以界面新增数据源相关信息,提交后,保存到数据库 2、保存后的数据源需要动态生效,并且可以由用户动态切换选择使用哪个数据源 3、数据库保存了多个数据源的相关记录后,要求…...
【浏览器】缓存与存储
我是目录 浏览器缓存为什么需要浏览器缓存?对浏览器的缓存机制的理解协商缓存和强缓存的区别强缓存协商缓存 点击刷新按钮或者按 F5、按 CtrlF5 (强制刷新)、地址栏回车有什么区别? 浏览器本地存储前端储存的方式有哪些࿱…...

积鼎科技携手西北工业大学动力与能源学院共建复杂多相流仿真联合实验室
11月26日,复杂多相流仿真联合实验室揭牌仪式及技术研讨活动在西北工业大学动力与能源学院成功举办。复杂多相流仿真联合实验室是由西北工业大学动力与能源学院牵头,携手上海积鼎信息科技有限公司与三航铸剑(西安)科技发展有限公司…...

5. langgraph实现高级RAG (Adaptive RAG)
1. 数据准备 from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.document_loaders import WebBaseLoader from langchain_community.vectorstores import Chromaurls ["https://lilianweng.github.io/posts/2023-06-23-age…...

Postman设置接口关联,实现参数化
🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 postman设置接口关联 在实际的接口测试中,后一个接口经常需要用到前一个接口返回的结果, 从而让后一个接口能正常执行,这…...

代码随想录day02--链表
移除链表元素 题目 地址:https://leetcode.cn/problems/remove-linked-list-elements/description/ 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val val 的节点,并返回 新的头节点 。 思路是使用虚拟节点的…...

杰发科技AC7803——不同晶振频率时钟的配置
计算公式 PLL_POSDIV [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62] PLL_PREDIV_1 1 2 4 USE_XTAL 24M SYSCLK_FREQ 64M SYSCLK_DIVIDER 1 VCO USE_XTAL*…...

ArcGIS栅格影像裁剪工具
1、前言 在最近的栅格转矢量处理过程中,发现二值化栅格规模太大,3601*3601,并且其中的面元太过细碎,通过arcgis直接栅格转面有将近几十万的要素,拿这样的栅格数据直接运行代码,发现速度很慢还难以执行出来结…...

【查询目录】.NET开源 ORM 框架 SqlSugar 系列
.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…...
docker快速安装zookeeper
一、拉取镜像 docker pull zookeeper:3.9.3 二、启动zookeeper docker run --restartalways -d --name zookeeper -p 2181:2181 -v /etc/localtime:/etc/localtime zookeeper:3.9.3 如果需要挂载zookeeper文件及目录,则参数增加: -v /mydata/zookeeper/d…...
MySQL中如何减少回表
在MySQL中,回表是指在使用非聚集索引进行查询时,如果需要获取的数据不在索引页中,就需要根据索引页中的指针返回到数据表中查找实际数据行的过程。这个过程会增加额外的磁盘I/O操作,降低查询性能,特别是在查询大量数据…...

初始Python篇(7)—— 正则表达式
找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏: Python 目录 正则表达式的概念 正则表达式的组成 元字符 限定符 其他字符 正则表达式的使用 正则表达式的常见操作方法 match方法的…...
洛谷P1443 马的遍历
简单的bfs 题目链接 P1443 马的遍历 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目描述 有一个 nm 的棋盘,在某个点(x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。 输入格式 输入只有一行四个整数,分别为 n…...

代理IP地址的含义与设置指南
在数字化时代,互联网已经成为我们日常生活不可或缺的一部分。然而,在享受互联网带来的便利的同时,我们也面临着隐私泄露、访问限制等问题。代理IP地址作为一种有效的网络工具,能够帮助我们解决这些问题。本文将详细介绍代理IP地址…...
Vue--------导航守卫(全局,组件,路由独享)
全局导航守卫 beforeEach 全局前置守卫 afterEach 全局后置守卫 路由独享守卫 beforeEnter 路由独享守卫 组件导航守卫 beforeRouteEnter 进入组件前 beforeRouteUpdate 路由改变但是组件复调用 beforeRouteLeave 离开组件之前 执行顺…...

ElasticSearch7.x入门教程之全文搜索(七)
文章目录 前言一、多条件查询:bool query二、更加精准查询:dis_max query总结 前言 这里再接着上一篇文章继续记录。非常感谢江南一点雨松哥的文章。 欢迎大家去查看,地址:http://www.javaboy.org 一、多条件查询:boo…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...

React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...

R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...