当前位置: 首页 > 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;用于…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

适应性Java用于现代 API:REST、GraphQL 和事件驱动

在快速发展的软件开发领域&#xff0c;REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名&#xff0c;不断适应这些现代范式的需求。随着不断发展的生态系统&#xff0c;Java 在现代 API 方…...