当前位置: 首页 > news >正文

【JAVA进阶篇教学】第十三篇:Java中volatile关键字讲解

博主打算从0-1讲解下java进阶篇教学,今天教学第十三篇:volatile关键字讲解。

在 Java 中,volatile关键字是一种轻量级的同步机制,用于确保变量的可见性和禁止指令重排序。本文将详细解释volatile关键字的工作原理、可见性保证以及与其他锁的相似之处,并通过代码示例进行说明。

目录

一、volatile关键字作用 

二、volatile关键字原理

三、volatile关键字的可见性

四、volatile关键字与锁的相似之处

五、volatile关键字的禁止指令重排序

六、总结


一、volatile关键字作用 

volatile 关键字用于修饰变量,确保多线程环境下对该变量的读写操作是可见的。具体来说,当一个线程修改了 volatile 变量的值时,其他线程能够立即看到这个修改,从而避免了线程之间的数据不一致性问题。

二、volatile关键字原理

volatile 关键字的可见性是通过在编译器和运行时进行一系列优化来实现的。在编译器层面,volatile 变量的读写操作会插入内存屏障指令,确保了线程在进行读写操作时能够从主内存中读取最新的值或将修改后的值刷新到主内存中。在运行时,JVM 会确保对 volatile 变量的操作是原子的,从而保证了多线程环境下的可见性。

注意:volatile并不能保证数据的原子性!

三、volatile关键字的可见性

volatile关键字可以确保变量的可见性。当一个变量被声明为volatile时,它告诉 Java 虚拟机(JVM),这个变量可能会被多个线程同时访问,并且线程对该变量的修改对于其他线程是可见的。

以下是一个简单的示例代码,演示了volatile关键字的可见性:

public class VolatileVisibilityExample {private volatile boolean flag = false;public void setFlag(boolean value) {flag = value;}public boolean isFlagSet() {return flag;}public static void main(String[] args) {VolatileVisibilityExample example = new VolatileVisibilityExample();// 创建并启动线程Thread thread = new Thread(() -> {while (!example.isFlagSet()) {// 等待 flag 变为 true}System.out.println("Flag 已设置为 true");});thread.start();// 修改 flag 的值example.setFlag(true);}
}

在上述示例中,我们创建了一个名为flag的volatile变量,并在一个线程中不断检查它的值。在主线程中,我们修改了flag的值,并期望子线程能够立即看到这个修改。由于flag是volatile变量,所以线程对flag的修改对于其他线程是可见的,子线程将立即退出循环并输出"Flag 已设置为 true"。

四、volatile关键字与锁的相似之处

  • volatile关键字和锁都可以用于实现线程之间的同步,但它们的实现方式和适用场景有所不同。
  • volatile关键字是一种轻量级的同步机制,它不会引起线程的阻塞和唤醒,因此执行效率较高。但是,volatile关键字只能保证变量的可见性,不能保证原子性。如果需要实现原子性操作,需要使用锁或其他同步机制。
  • 锁是一种更重量级的同步机制,它可以保证原子性、可见性和有序性。锁的实现通常基于操作系统的互斥锁或信号量,因此执行效率较低。但是,锁可以用于实现更复杂的同步逻辑,例如实现临界区、读写锁等。

五、volatile关键字的禁止指令重排序

  • 除了可见性保证之外,volatile关键字还可以禁止指令重排序。指令重排序是一种优化技术,它可以在不改变程序语义的情况下,重新排列指令的执行顺序,以提高执行效率。但是,指令重排序可能会导致多线程程序出现问题,例如竞态条件、数据不一致等。
  • volatile关键字通过添加内存屏障来禁止指令重排序。内存屏障是一种硬件机制,它可以确保在执行当前指令之前,先执行之前的所有内存操作,并且在执行当前指令之后,再执行之后的所有内存操作。这样可以保证指令的执行顺序不会被重排序。

以下是一个简单的示例代码,演示了volatile关键字的禁止指令重排序:

public class VolatileMemoryOrderingExample {private volatile int value = 0;public void setValue(int value) {this.value = value;}public int getValue() {return value;}public static void main(String[] args) {VolatileMemoryOrderingExample example = new VolatileMemoryOrderingExample();// 创建并启动线程Thread thread = new Thread(() -> {int expectedValue = 1;while (example.getValue()!= expectedValue) {// 等待 value 变为 1}System.out.println("Value 已设置为 1");});thread.start();// 修改 value 的值example.setValue(1);}
}

在上述示例中,我们创建了一个名为value的volatile变量,并在一个线程中不断检查它的值。在主线程中,我们修改了value的值,并期望子线程能够立即看到这个修改。由于value是volatile变量,并且使用了内存屏障来禁止指令重排序,所以线程对value的修改对于其他线程是可见的,子线程将立即退出循环并输出"Value 已设置为 1"。

六、总结

volatile关键字是 Java 中的一种轻量级同步机制,它可以确保变量的可见性和禁止指令重排序。volatile关键字适用于多线程环境下的变量共享,例如状态标志、计数器等。与锁相比,volatile关键字的执行效率较高,但不能保证原子性。如果需要实现原子性操作,需要使用锁或其他同步机制。

相关文章:

【JAVA进阶篇教学】第十三篇:Java中volatile关键字讲解

博主打算从0-1讲解下java进阶篇教学,今天教学第十三篇:volatile关键字讲解。 在 Java 中,volatile关键字是一种轻量级的同步机制,用于确保变量的可见性和禁止指令重排序。本文将详细解释volatile关键字的工作原理、可见性保证以及…...

蓝桥杯-地宫取宝

X 国王有一个地宫宝库,是 nm 个格子的矩阵,每个格子放一件宝贝,每个宝贝贴着价值标签。 地宫的入口在左上角,出口在右下角。 小明被带到地宫的入口,国王要求他只能向右或向下行走。 走过某个格子时,如果那个…...

带头单链表 C++实现

节点定义 带头单链表&#xff1a;我们只需要一个结点指针指向整个链表的第一个节点&#xff0c;这样我们就可以通过next指针访问整个链表内的所有节点 template<class T> struct ListNode {T _val;ListNode* _next;ListNode(const T &val):_val(val),_next(nullptr){…...

学习c#第24天 枚举类型

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace enumType { //定义枚举 public enum Week { 星期一, 星期二, 星期三, 星期四, 星期…...

TensorFlow运行bug汇总

1、ImportError: urllib3 v2.0 only supports OpenSSL 1.1.1 解决方案 pip install urllib31.26.15 -i https://pypi.tuna.tsinghua.edu.cn/simple 升级或者降级 (TF2.1) C:\Users\Administrator>pip install urllib31.26.15 -i https://pypi.tuna.tsinghua.edu.cn/sim…...

docker部署调度程序

Dockerfile(构建初始镜像) # python:3.8-slim-buster为精简版的python FROM python:3.8-slim-buster # 1059为组的id,newgroup为组名,1088为用户的id,newuser为新用户 RUN groupadd -g 1059 newgroup && \useradd -g -u 1088 -g newgroup -m newuser USER newuser RUN…...

websocket和http协议的区别

ws(websocket)协议和http协议是两种不同的协议。 http&#xff1a;http是一种用于传输超文本的应用层协议&#xff0c;通常用于web端浏览器和web端服务器之间传输数据。http也是基于tcp的&#xff0c;但是HTTP只能在同一时刻单向发送消息&#xff0c;是一种半双工通信。&#…...

CSS之定位

目录 CSS定位为什么需要定位定位组成定位的叠放顺序拓展 CSS定位 为什么需要定位 浮动可以让多个块级盒子一行没有缝隙排列显示&#xff0c;经常用于横向排列盒子定位则是可以让盒子自由的在某个盒子内移动位置或者固定屏幕中的某个位置&#xff0c;并且可以压住其他盒子 定…...

[IM002][Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序

解决办法&#xff1a; 安装驱动 下载 ODBC Driver for SQL Server - ODBC Driver for SQL Server | Microsoft Learn...

神经网络复习--神经网络算法模型及BP算法

文章目录 神经网络模型的构成BP神经网络 神经网络模型的构成 三种表示方式&#xff1a; 神经网络的三要素&#xff1a; 具有突触或连接&#xff0c;用权重表示神经元的连接强度具有时空整合功能的输入信号累加器激励函数用于限制神经网络的输出 感知神经网络 BP神经网络 …...

【Java】/*方法的使用-快速总结*/

目录 一、什么是方法 二、方法的定义 三、实参和形参的关系 四、方法重载 五、方法签名 一、什么是方法 Java中的方法可以理解为C语言中的函数&#xff0c;只是换了个名称而已。 二、方法的定义 1. 语法格式&#xff1a; public static 返回类型 方法名 (形参列表) { //方…...

kotlin中协程相关

协程 用同步的方式写出异步的效果协程最重要的是通过非阻塞挂起和恢复实现了异步代码的同步编写方式挂起函数(suspend)不一定就是在子线程中执行的&#xff0c;但是通常在定义挂起函数时都会为它指定其他线程&#xff0c;这样挂起才有意义解决多层嵌套回调 协程不是线程&…...

(自适应手机端)物流运输快递仓储网站模板 - 带三级栏目

(自适应手机端)物流运输快递仓储网站模板 - 带三级栏目PbootCMS内核开发的网站模板&#xff0c;该模板适用于物流运输网站、仓储货运网站等企业&#xff0c;当然其他行业也可以做&#xff0c;只需要把文字图片换成其他行业的即可&#xff1b;自适应手机端&#xff0c;同一个后台…...

Navicat导出表结构到Excel或Word

文章目录 sql语句复制到excel复制到Word sql语句 SELECTcols.COLUMN_NAME AS 字段,cols.COLUMN_TYPE AS 数据类型,IF(pks.CONSTRAINT_TYPE PRIMARY KEY, YES, NO) AS 是否为主键,IF(idxs.INDEX_NAME IS NOT NULL, YES, NO) AS 是否为索引,cols.IS_NULLABLE AS 是否为空,cols.…...

Golang编译优化——稀疏条件常量传播

文章目录 一、概述二、稀疏条件常量传播2.1 初始化worklist2.2 构建def-use链2.3 更新值的lattice2.4 传播constant值2.5 替换no-constant值 一、概述 常量传播&#xff08;constant propagation&#xff09;是一种转换&#xff0c;对于给定的关于某个变量 x x x和一个常量 c …...

人工智能培训讲师咨询叶梓介绍及智能医疗技术与ChatGPT临床应用三日深度培训提纲

1、授课老师简介 叶梓&#xff0c;上海交通大学计算机专业博士毕业&#xff0c;高级工程师。主研方向&#xff1a;数据挖掘、机器学习、人工智能。历任国内知名上市IT企业的AI技术总监、资深技术专家&#xff0c;市级行业大数据平台技术负责人。 长期负责城市信息化智能平台的…...

HCIP(BGP综合实验)--8

一&#xff1a;实验要求 二&#xff1a;实现过程 &#xff08;一&#xff09;配置IP地址&#xff1a; AR1: [AR1]int g0/0/0 [AR1-GigabitEthernet0/0/0]ip add 12.1.1.1 24 [AR1-GigabitEthernet0/0/0]int l0 [AR1-LoopBack0]ip add 172.16.0.1 32 [AR1-LoopBack0]int l1 […...

深入理解C++中的Vector容器:用容器构建高效程序

文章目录 vector介绍vector常用的成员函数有关vector定义的函数vector的迭代器使用vector关于空间操作的成员函数vector的增删查改 总结 vector介绍 在C语言的库中包含有公共数据结构的实现&#xff0c;C的这个部分内容就是众所周知的STL&#xff08;标准模版库&#xff09;&a…...

目标检测YOLO实战应用案例100讲-基于深度学习的交通场景多尺度目标检测算法研究与应用(下)

目录 3.2 基于空洞卷积的特征融合模块设计 3.3 改进k-means聚类算法的anchor尺寸优化设计...

react 类组件 和 函数组件 声明周期 对比

React 的类组件和函数组件在生命周期方面存在一些差异。以下是它们之间的对比&#xff1a; 类组件的生命周期 React 类组件的生命周期可以分为三个阶段&#xff1a;挂载、更新和卸载。 1、挂载阶段&#xff1a; constructor()&#xff1a;组件实例化时调用&#xff0c;用于…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

C# 表达式和运算符(求值顺序)

求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如&#xff0c;已知表达式3*52&#xff0c;依照子表达式的求值顺序&#xff0c;有两种可能的结果&#xff0c;如图9-3所示。 如果乘法先执行&#xff0c;结果是17。如果5…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...