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

关于对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}{规定:} 规定:

  1. 线程解锁之前必须将共享变量刷新回主内存;
  2. 线程加锁之前必须读取主内存中变量的最新值到工作空间;
  3. 解锁和加锁必须是同一把锁。

大家可能不解其意,这就需要涉及另一个概念: 线程空间 \color{green}{线程空间} 线程空间.。
什么是线程空间? \color{grey}{什么是线程空间?} 什么是线程空间?
程序执行JMM规范的实体是线程,当线程创建时,JMM会为其创建一个私有内存(也称为 工作内存、本地内存或栈空间 工作内存、本地内存或栈空间 工作内存、本地内存或栈空间)。JMM规定所有变量都保存在主内存,线程访问变量时需为变量创建一个副本至工作内存进行操作,完成后将变量值返回主内存,且线程通信在主内存进行。

2、关于volatile

并发编程的三个概念:

  1. 可见性: \color{green}{可见性:} 可见性:指线程对变量的修改,其他线程可见;
  2. 原子性: \color{blue}{原子性:} 原子性:指线程对变量的操作的整个过程不会被阻塞或分割;
  3. 有序性: \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关键字可以解决这两种情形下的线程安全问题。

  1. 多线程并发访问变量,线程体中不存在非原子操作的情况;
  2. 弥补 双重同步锁 \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关键字的理解与简述

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/134430096 出自【进步*于辰的博客】 启发之作&#xff1a;Java volatile关键字最全总结&#xf…...

37 _ 贪心算法:如何用贪心算法实现Huffman压缩编码?

基础的数据结构和算法我们基本上学完了,接下来几节,我会讲几种更加基本的算法。它们分别是贪心算法、分治算法、回溯算法、动态规划。更加确切地说,它们应该是算法思想,并不是具体的算法,常用来指导我们设计具体的算法和编码等。 贪心、分治、回溯、动态规划这4个算法思想…...

Unity中Shader矩阵的逆矩阵

文章目录 前言一、逆矩阵的表示二、逆矩阵的作用四、逆矩阵的计算五、顺序的重要性六、矩阵的逆总结1、求矩阵的逆前&#xff0c;这个矩阵必须得是个方阵2、只有 A x A ^-1^ A^-1^ x A 1时&#xff0c;A的逆才是A^-1^3、求2x2矩阵的逆&#xff1a;交换 a 和 b 的位置&#xf…...

我给网站做公安备案年度安全评估

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 差不多从2020年开始&#xff0c;我们的网站每年11月左右就要去公安备案做一次年度的安全评估&#xff0c;而现在又新增了APP和小程序备案。如下图所示&#xff1a; 评估的内容也很简单&#xff0c…...

iceoryx(冰羚)-通信中间件解析

iceoryx(冰羚)-简介 iceoryx(冰羚)-Architecture iceoryx(冰羚)-Service Discovery iceoryx(冰羚)-examples-callbacks iceoryx(冰羚)-Listener设计 [iceoryx(冰羚)-ipc消息通信] [iceoryx(冰羚)-共享内存实现]...

Windows系统CMake+VS编译protobuf

目录 一些名词CMake构建VS工程下载protobuf源码下载CMake编译QT中使用 方案二失败&#xff1a;CMakeQT自带的Mingw编译参考链接 一些名词 lib dll lib库实际上分为两种&#xff0c;一种是静态链接lib库或者叫做静态lib库&#xff0c;另一种叫做动态链接库dll库的lib导入库或称…...

HarmonyOS开发(三):ArkTS基础

1、ArkTS演进 Mozilla创建了JS ---> Microsoft创建了TS ----> Huawei进一步推出ArkTS 从最初的基础逻辑交互&#xff08;JS&#xff09;,到具备类型系统的高效工程开发&#xff08;TS&#xff09;,再到融合声明式UI、多维状态管理等丰富的应用开发能力&…...

Java排序算法之堆排序

图解 堆排序是一种常见的排序算法&#xff0c;它借助了堆这种数据结构。堆是一种完全二叉树&#xff0c;它可以分为两种类型&#xff1a;最大堆和最小堆。在最大堆中&#xff0c;每个结点的值都大于等于它的子结点的值&#xff0c;而在最小堆中&#xff0c;每个结点的值都小于等…...

『GitHub项目圈选02』一款可实现视频自动翻译配音为其他语言的开源项目

&#x1f525;&#x1f525;&#x1f525;本周GitHub项目圈选****: 主要包含视频翻译、正则填字游戏、敏感词检测、聊天机器人框架、AI 换脸、分布式数据集成平台等热点项目。 1、pyvideotrans pyvideotrans 是一个视频翻译工具&#xff0c;可将一种语言的视频翻译为另一种语…...

Unity - Cinemachine

动态获取Cinemachine的内部组件 vCam.GetCinemachineComponent<T>() 动态修改Cinemachine的Transposer属性 var vCamComp transfrom.GetComponent<CinemachineVirtualCamera>(); var transposerComp vCamComp.GetCinemachineComponent<CinemachineTransposer&…...

准备搞OpenStack了,先装一台最新的Ubuntu 23.10

正文共&#xff1a;1113 字 25 图&#xff0c;预估阅读时间&#xff1a;2 分钟 依稀记得前面发了一篇Ubuntu的安装文档&#xff08;66%的经验丰富开发者和69%的学生更喜欢的Ubuntu的安装初体验&#xff09;&#xff0c;当时安装的是20.04.3的版本&#xff0c;现在看来已经是非常…...

Android 12 客制化修改初探-Launcher/Settings/Bootanimation

Android 12 使用 Material You 打造的全新系统界面&#xff0c;富有表现力、活力和个性。使用重新设计的微件、AppSearch、游戏模式和新的编解码器扩展您的应用。支持隐私信息中心和大致位置等新的保护功能。使用富媒体内容插入功能、更简便的模糊处理功能、经过改进的原生调试…...

【JavaEE初阶】 HTML基础详解

文章目录 &#x1f38b;什么是HTML&#xff1f;&#x1f340;HTML 结构&#x1f6a9;认识标签&#x1f6a9;HTML 文件基本结构&#x1f6a9;快速生成代码框架 &#x1f384;HTML 常见标签&#x1f6a9;注释标签&#x1f6a9;标题标签: h1-h6&#x1f6a9;段落标签: p&#x1f6…...

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图的原理是检验实际累积概率分布与理论累积概率分布是否吻合。若吻合&#xf…...

浅尝:iOS的CoreGraphics和Flutter的Canvas

iOS的CoreGraphic 基本就是创建一个自定义的UIView&#xff0c;然后重写drawRect方法&#xff0c;在此方法里使用UIGraphicsGetCurrentContext()来绘制目标图形和样式 #import <UIKit/UIKit.h>interface MyGraphicView : UIView endimplementation MyGraphicView// Onl…...

网络安全黑客技术自学

前言 一、什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻与防…...

【文件读取/包含】任意文件读取漏洞 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关键字。 一、单例模式 设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。就像是经典的棋谱&#xff0c;不同的棋局&#xff0c;我…...

深入Android S(12.0) 探索 Android Framework 之 SystemServer 进程启动详解

深入学习 Android Framework 第三&#xff1a;深入Android S(12.0) 探索 Android Framework 之 SystemServer 进程启动详解 文章目录 深入学习 Android Framework前言一、Android 系统的启动流程1. 流程图2. 启动流程概述 二、源码详解1. 时序图2. 源代码1、ZygoteInit # main…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用

一、方案背景​ 在现代生产与生活场景中&#xff0c;如工厂高危作业区、医院手术室、公共场景等&#xff0c;人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式&#xff0c;存在效率低、覆盖面不足、判断主观性强等问题&#xff0c;难以满足对人员打手机行为精…...

【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)

LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 题目描述解题思路Java代码 题目描述 题目链接&#xff1a;LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...

【堆垛策略】设计方法

堆垛策略的设计是积木堆叠系统的核心&#xff0c;直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法&#xff0c;涵盖基础规则、优化算法和容错机制&#xff1a; 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则&#xff1a; 大尺寸/重量积木在下&#xf…...