关于对Java中volatile关键字的理解与简述
【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权)
https://blog.csdn.net/m0_69908381/article/details/134430096
出自【进步*于辰的博客】
启发之作:Java volatile关键字最全总结:原理剖析与实例讲解(简单易懂)(转发)。
参考笔记二,P73、P74.1。
文章目录
- 1、关于JMM规范
- 2、关于`volatile`
- 3、关于`volatile`的运用
- 4、最后
在学习
volatile关键字之前,我们先了解一下JMM规范和并发编程中的三个概念。
1、关于JMM规范
什么是 J M M ? \color{grey}{什么是JMM?} 什么是JMM?
JMM(Java module memory,Java内存模型)是一个抽象概念,并不真实存在于内存。它是用于定义程序中各个变量(成员变量、类变量、数组元素等)的一组规范和规则,指定变量的访问方式。
规定: \color{red}{规定:} 规定:
- 线程解锁之前必须将共享变量刷新回主内存;
- 线程加锁之前必须读取主内存中变量的最新值到工作空间;
- 解锁和加锁必须是同一把锁。
大家可能不解其意,这就需要涉及另一个概念: 线程空间 \color{green}{线程空间} 线程空间.。
什么是线程空间? \color{grey}{什么是线程空间?} 什么是线程空间?
程序执行JMM规范的实体是线程,当线程创建时,JMM会为其创建一个私有内存(也称为 工作内存、本地内存或栈空间 工作内存、本地内存或栈空间 工作内存、本地内存或栈空间)。JMM规定所有变量都保存在主内存,线程访问变量时需为变量创建一个副本至工作内存进行操作,完成后将变量值返回主内存,且线程通信在主内存进行。
2、关于volatile
并发编程的三个概念:
- 可见性: \color{green}{可见性:} 可见性:指线程对变量的修改,其他线程可见;
- 原子性: \color{blue}{原子性:} 原子性:指线程对变量的操作的整个过程不会被阻塞或分割;
- 有序性: \color{brown}{有序性:} 有序性:也称为 “指令重排” \color{red}{“指令重排”} “指令重排”,指程序运行时,编译器基于提高性能需要,以指令间的数据依赖性作为依据对指令进行重新排列。执行顺序:编译器重排 → 指令并行重排 → 内存系统重排。
volatile 是什么? \color{grey}{是什么?} 是什么?
volatile是一种轻量级的同步机制,而synchronized是一种重量级的同步机制(“级”是指对变量访问的限制程度)。volatile遵循JMM规范实现了可见性和有序性,但不保证原子性。因此,限制线程在访问由volatile修饰的变量时,从主内存获取数据,而不是从工作内存,在数据操作完成后再刷新回主内存,故在保证原子性的情况下,可实现线程安全。
注:如何保证原子性?如程序中不存在多线程对变量进行非原子性操作,举个例:a++是原子操作,而a+=1不是。
volatile 的一个经典应用: \color{red}{的一个经典应用:} 的一个经典应用:
关于单例模式,可查阅博文【关于对【单例模式_java】的理解与简述】。
从文中可知, “双重检测机制” \color{green}{“双重检测机制”} “双重检测机制”可解决“懒汉式”的线程安全问题。其实,“双重同步锁”也有漏洞。
以那篇博文的示例为例:
instance = new Singleton();
实例化分为三步:1、创建实例,分配内存;2、实例初始化;3、令instance指向此实例。其中,2和3都依赖于1,而2与3之间没有依赖关系,故指令重排会将2与3对调(原因可能是实例初始化耗时较长)。因此,当instance指向实例时,实例可能还未初始化,下一个线程就会出现并发问题(暂不清楚原因),用volatile禁止指令重排即可解决。
3、关于volatile的运用
学以致用才是检验学习效果最好的方法。从上文可知,volatile关键字可以解决这两种情形下的线程安全问题。
- 多线程并发访问变量,线程体中不存在非原子操作的情况;
- 弥补 双重同步锁 \color{green}{双重同步锁} 双重同步锁的漏洞。
那我们就一一测试检测一下。
1、情形一:创建10个线程对同一个成员变量并发修改1万次。
示例。
volatile int a;
public static void main(String[] args) throws Exception {C c1 = new C();// C 是当前类名int i = 10;while (i-- > 0) {new Thread(() -> {int n = 10000;while (n-- > 0) {c1.a++;}}).start();}Thread.sleep(10000);// 主线程停留10s足以保证10个子线程运行完成System.out.println(c1.a);
}
最后c1.a的输出结果并不是100000(10s足够10个子线程执行完成)。可见,并未解决线程安全问题。
2、情形二:多线程并发调用newInstance()获取单例模式类实例。
实体类。
class SingleTon {private static SingleTon instance;private SingleTon() {}public static SingleTon newInstance() {if (instance == null) {synchronized (SingleTon.class) {if (instance == null) {instance = new SingleTon();}}}return instance;}
}
测试:创建一万个线程并发调用newInstance(),判断获取的实例是否都为单例。
List<SingleTon> list = new Vector<>();
int i = 10000;
while (i-- > 0) {new Thread(() -> {SingleTon s1 = SingleTon.getInstance();if (list.size() > 0 && list.indexOf(s1) == -1)System.out.println("违反单例");// 未执行list.add(s1);}).start();
}
Thread.sleep(1000);
System.out.println(list.size());// 10000
Vector 类线程同步,故list.add(s1)也是线程同步的。
未打印“违反单例”,表示list中存储的所有s1都指向同一个实例,保证了“单例”,说明线程安全。
不过,还证明不了这是volatile的功劳,因为 双重检测机制 \color{blue}{双重检测机制} 双重检测机制本身对线程安全就有很大的保证性。
于是,我把10000改成了100000,好吧。。。还是未打印“违反单例”,看来双重同步锁真的很强大。
4、最后
大家肯定也看出来了,在上面的示例中,我的本意是想创建十万个线程调用newInstance(),通过是否打印“违反单例”来触发 双重同步锁 \color{brown}{双重同步锁} 双重同步锁的漏洞,然后用volatile声明instance来解决线程安全问题,可我失败了。。。
大家也看得出来,我对volatile关键字的理解还不够透彻,毕竟哪有这样测试的。
因此,本文的目的是为了让大家对volatile关键字有一个初步的了解,我继续努力!!
本文完结。
相关文章:
关于对Java中volatile关键字的理解与简述
【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://blog.csdn.net/m0_69908381/article/details/134430096 出自【进步*于辰的博客】 启发之作:Java volatile关键字最全总结…...
37 _ 贪心算法:如何用贪心算法实现Huffman压缩编码?
基础的数据结构和算法我们基本上学完了,接下来几节,我会讲几种更加基本的算法。它们分别是贪心算法、分治算法、回溯算法、动态规划。更加确切地说,它们应该是算法思想,并不是具体的算法,常用来指导我们设计具体的算法和编码等。 贪心、分治、回溯、动态规划这4个算法思想…...
Unity中Shader矩阵的逆矩阵
文章目录 前言一、逆矩阵的表示二、逆矩阵的作用四、逆矩阵的计算五、顺序的重要性六、矩阵的逆总结1、求矩阵的逆前,这个矩阵必须得是个方阵2、只有 A x A ^-1^ A^-1^ x A 1时,A的逆才是A^-1^3、求2x2矩阵的逆:交换 a 和 b 的位置…...
我给网站做公安备案年度安全评估
我是卢松松,点点上面的头像,欢迎关注我哦! 差不多从2020年开始,我们的网站每年11月左右就要去公安备案做一次年度的安全评估,而现在又新增了APP和小程序备案。如下图所示: 评估的内容也很简单,…...
iceoryx(冰羚)-通信中间件解析
iceoryx(冰羚)-简介 iceoryx(冰羚)-Architecture iceoryx(冰羚)-Service Discovery iceoryx(冰羚)-examples-callbacks iceoryx(冰羚)-Listener设计 [iceoryx(冰羚)-ipc消息通信] [iceoryx(冰羚)-共享内存实现]...
Windows系统CMake+VS编译protobuf
目录 一些名词CMake构建VS工程下载protobuf源码下载CMake编译QT中使用 方案二失败:CMakeQT自带的Mingw编译参考链接 一些名词 lib dll lib库实际上分为两种,一种是静态链接lib库或者叫做静态lib库,另一种叫做动态链接库dll库的lib导入库或称…...
HarmonyOS开发(三):ArkTS基础
1、ArkTS演进 Mozilla创建了JS ---> Microsoft创建了TS ----> Huawei进一步推出ArkTS 从最初的基础逻辑交互(JS),到具备类型系统的高效工程开发(TS),再到融合声明式UI、多维状态管理等丰富的应用开发能力&…...
Java排序算法之堆排序
图解 堆排序是一种常见的排序算法,它借助了堆这种数据结构。堆是一种完全二叉树,它可以分为两种类型:最大堆和最小堆。在最大堆中,每个结点的值都大于等于它的子结点的值,而在最小堆中,每个结点的值都小于等…...
『GitHub项目圈选02』一款可实现视频自动翻译配音为其他语言的开源项目
🔥🔥🔥本周GitHub项目圈选****: 主要包含视频翻译、正则填字游戏、敏感词检测、聊天机器人框架、AI 换脸、分布式数据集成平台等热点项目。 1、pyvideotrans pyvideotrans 是一个视频翻译工具,可将一种语言的视频翻译为另一种语…...
Unity - Cinemachine
动态获取Cinemachine的内部组件 vCam.GetCinemachineComponent<T>() 动态修改Cinemachine的Transposer属性 var vCamComp transfrom.GetComponent<CinemachineVirtualCamera>(); var transposerComp vCamComp.GetCinemachineComponent<CinemachineTransposer&…...
准备搞OpenStack了,先装一台最新的Ubuntu 23.10
正文共:1113 字 25 图,预估阅读时间:2 分钟 依稀记得前面发了一篇Ubuntu的安装文档(66%的经验丰富开发者和69%的学生更喜欢的Ubuntu的安装初体验),当时安装的是20.04.3的版本,现在看来已经是非常…...
Android 12 客制化修改初探-Launcher/Settings/Bootanimation
Android 12 使用 Material You 打造的全新系统界面,富有表现力、活力和个性。使用重新设计的微件、AppSearch、游戏模式和新的编解码器扩展您的应用。支持隐私信息中心和大致位置等新的保护功能。使用富媒体内容插入功能、更简便的模糊处理功能、经过改进的原生调试…...
【JavaEE初阶】 HTML基础详解
文章目录 🎋什么是HTML?🍀HTML 结构🚩认识标签🚩HTML 文件基本结构🚩快速生成代码框架 🎄HTML 常见标签🚩注释标签🚩标题标签: h1-h6🚩段落标签: pǶ…...
C# Socket通信从入门到精通(10)——如何检测两台电脑之间的网络是否通畅
前言: 我们在完成了socket通信程序开发以后,并且IP地址也设置好以后,可以先通过一些手段来测试两台电脑之间的网络是否通畅,如果确认了网络通畅以后,我们再测试我们编写的Socket程序。 1、同时按下键盘的windows键+"R"键,如下图: 下面两张图是两种键盘的情…...
python科研绘图:P-P图与Q-Q图
目录 什么是P-P图与Q-Q图 分位数 百分位数 Q-Q图步骤与原理 Shapiro-Wilk检验 绘制Q-Q图 绘制P-P图 什么是P-P图与Q-Q图 P-P图和Q-Q图都是用于检验样本的概率分布是否服从某种理论分布。 P-P图的原理是检验实际累积概率分布与理论累积概率分布是否吻合。若吻合…...
浅尝:iOS的CoreGraphics和Flutter的Canvas
iOS的CoreGraphic 基本就是创建一个自定义的UIView,然后重写drawRect方法,在此方法里使用UIGraphicsGetCurrentContext()来绘制目标图形和样式 #import <UIKit/UIKit.h>interface MyGraphicView : UIView endimplementation MyGraphicView// Onl…...
网络安全黑客技术自学
前言 一、什么是网络安全 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域,都有攻与防…...
【文件读取/包含】任意文件读取漏洞 afr_3
1.1漏洞描述 漏洞名称任意文件读取漏洞 afr_3漏洞类型文件读取/包含漏洞等级⭐⭐⭐⭐⭐漏洞环境docker攻击方式 1.2漏洞等级 高危 1.3影响版本 暂无 1.4漏洞复现 1.4.1.基础环境 靶场docker工具BurpSuite 1.4.2.环境搭建 1.创建docker-compose.yml文件 version: 3.2 servi…...
第四章:单例模式与final
系列文章目录 文章目录 系列文章目录前言一、单例模式二、final 关键字总结 前言 单例模式与final关键字。 一、单例模式 设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。就像是经典的棋谱,不同的棋局,我…...
深入Android S(12.0) 探索 Android Framework 之 SystemServer 进程启动详解
深入学习 Android Framework 第三:深入Android S(12.0) 探索 Android Framework 之 SystemServer 进程启动详解 文章目录 深入学习 Android Framework前言一、Android 系统的启动流程1. 流程图2. 启动流程概述 二、源码详解1. 时序图2. 源代码1、ZygoteInit # main…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
