Java --- JUC之volatile

news2024/12/24 8:20:10

目录

一、volatile两大特点

二、volatile的内存语义

三、volatile内存屏障

四、volatile四大屏障

五、volatile的特性

六、volatile使用场景


一、volatile两大特点

1、可见性 2、有序性

二、volatile的内存语义

1、当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值立即刷新回主内存中。

2、、当读一个volatile变量时,JMM会把该线程对应的本地内存设置为无效,重新回到主内存中读取最新共享变量。

3、volatile的写内存语义是直接刷新到主内存中,读的内存语义是直接从主内存中读取。

三、volatile内存屏障

内存屏障(也称内存栅栏,屏障指令,是一类同步屏障指令,是CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后才可以开始执行此点之后的操作),避免代码重新排序。内存屏障其实就是一个JVM指令,Java内存模型的重排规则会要求Java编译器在生产JVM指令时插入特定的内存屏障指令,通过这些内存屏障指令,volatile实现了Java内存模型中的可见性和有序性(禁重排),但volatile无法保证原子性。

内存屏障之前的所有写操作都要回写到主内存,

内存屏障之后的所有读操作都能获得内存屏障之前的所有写操作的最新结果(实现了可见性)。

写屏障:告诉处理器在写屏障之前将所有存储都缓存中的数据同步到主内存。就是当看到Store屏障指令,就必须把该指令之前所有写入指令执行完毕。

读屏障:处理器在读屏障之后的读操作,都在读屏障之后执行。也就是在Load屏障指令之后就能够保证后面的读取数据指令一定能够读取到最新的数据。

因此重排序时,不允许把内存屏障之后的指令重排序到内存屏障之前。也就是对一个volatile变量的写,先行发生于任意后续对这个volatile变量的读,也叫写后读。

四、volatile四大屏障

1、LoadLoad      Load1;LoadLoad;Load2    保证load1的读取操作在load2及后续读取操作之前执行。

2、StoreStore     Store1:StoreStore;Store2 在store2及其后的写操作执行前,保证store1的写操作已刷新到主内存

3、LoadStore   Load1;Loadstore;Store2   在store2及其后的写操作执行前,保证load1的读操作已读取结束

4、StoreLoad   Store1;StoreLoad;Load2  保证store1的写操作已刷新到主内存之后,load2及其后的读操作才能执行。

五、volatile的特性

1、保证可见性:保证不同线程对某个变量完成操作后结果及时可见,即该共享变量一旦改变所有线程即可见。

public class volatiles {
    public static volatile boolean flag = true;
    public static void main(String[] args) throws InterruptedException {
        new Thread(()->{
            System.out.println(Thread.currentThread().getName() + "\t开始执行");
            while (flag){

            }
            System.out.println(Thread.currentThread().getName() + "\tflag被修改为false");
        },"t1").start();
        TimeUnit.SECONDS.sleep(2);
        flag = false;
        System.out.println(Thread.currentThread().getName() + "flag修改完成");
    }
}

2、没有原子性:volatile变量的复合操作不具有原子性

public class volatiles {
    public static void main(String[] args) {
        Student student = new Student();
        for (int i = 1; i <=10 ; i++) {
            new Thread(()->{
                for (int j = 1; j <=1000 ; j++) {
                    student.addNumber();
                }
            },String.valueOf(i)).start();
        }
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(student.number);
    }
}
class Student{
    volatile int number;
    public void addNumber(){
        number++;
    }
}

 对于volatile变量具备可见性,JVM只是保证从主内存加载到线程工作内存的值是最新的,也仅是数据加载时是最新。但是多线程环境下,“数据计算”和“数据赋值”操作可能多次出现,若数据在加载之后,若主内存volatile修饰变量发生修改之后,线程工作内存中的操作将会作废去读主内存最新值,操作出现写丢失问题。即各线程私有内存和主内存公共内存中变量不同步,进而导致数据不一致。由此可见volatile解决的是变量读时的可见性问题,但无法保证原子性,对于多线程修改主内存共享变量的场景必须使用加锁同步。

3、指令禁重排

重排序:是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段,有时候会改变程序语句的先后顺序。

不存在数据依赖关系,可以重排序;存在数据依赖关系,禁止重排序。但重排后的指令绝对不能改变原有的串行语义!

重排序的分类和执行流程:

 编译器优化的重排序:编译器在不改变单线程串行语义的前提下,可以重新调整指令的执行顺序

指令级并行的重排序:处理器使用指令级并行技术来将多条指令重叠执行,若不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。

内存系统的重排序:由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是乱序执行。

数据依赖性:若两个操作访问同一变量,且这个操作中有一个为写操作,此时两操作间就存在数据依赖性。

六、volatile使用场景

1、单一赋值:如Boolean类型变量等

2、状态标志,判断业务是否结束

3、开销较低的读、写策略

4、DCL双端锁的发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/135290.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言入门系列 - 共用体union,枚举enum,宏定义#define,条件编译,const与指针

C语言入门系列 - 共用体union,枚举enum&#xff0c;宏定义#define,条件编译,const与指针 第一节 C 语言基础以及基本数据类型 第二节 C 语言运算符 第三节 C 语言控制语句 第四节 C 语言自定义函数 第五节 C 语言修饰变量的关键字 第六节 C 语言构造数据类型–数组 第七节 C 语…

创建型模式

创建型模式 创建型模式对类的实例化过程进行了抽象&#xff0c;能够将软件中对象的创建和使用分离&#xff0c;使整个系统的设计更加符合单一职责原则。 什么是对象的创建与对象的使用分离&#xff1f; 一个女生想吃苹果&#xff0c;怎么办&#xff1f; 对象的创建和对象的使用…

TC275——04Blinky-LED

项目工程框架 项目驱动文件这个见过&#xff0c;三个main文件真的是开了眼&#xff0c;一个main代表一个核吗&#xff1f; 按照以往对实现LED闪烁的流程&#xff0c;一般是先配置时钟、再配置IO、延时&#xff0c;实现反转效果。 Blinky_LED.c 在驱动文件里&#xff1a; /*…

数据分析 -Hive学习 Day5

HIVE 核心技能之窗口函数 大家好呀&#xff0c;这节课我们学习 Hive 核心技能中最难的部分——窗口函数。窗口函数我们之前在学 MySQL 的时候有学过一些&#xff0c;但是只学了三个排序的窗口函数。这节课我们会学习更多的窗口函数&#xff0c;包括累计计算、分区排序、切片排…

nvm中node包管理器在windows中的使用

你要使用的 1/nuvm 只能在Linux 和 OS X 2/推荐使用nvm-windows&#xff0c;git上&#xff0c;我认为还可以就使用 操作 1/下载的git地址nvm-windows 2/好像要清除掉所有node&#xff0c;是个注意点 3/安装 4/路径上不允许存在空格&#xff0c;否则后面会各种报错 5…

读书笔记《硬件十万个为什么——开发流程篇》

大家好,这里是大话硬件。 今天想给大家分享上周末在家写的读书笔记,内容来源于重读《硬件十万个为什么——开发流程篇》这本书的一些启发和总结。 1. 为什么我要重读这本书籍? 这本书收到快递的时间是2022.8.26,拆开快递的那个晚上大约花了2个小时从头到尾快速浏览了一次…

(创建失败)小米万兆路由器里的Docker安装Redis7.0

小米2022年12月份发布了万兆路由器&#xff0c;里面可以使用Docker。 今天尝试在小米的万兆路由器里安装Redis7.0。 创建失败&#xff0c;有时间时确认是否可以解决。 Server cant set maximum open files to 10032 because of OS error: Operation not permitted. Current m…

【STM32 Cortex-M4核中断实验】

STM32 Cortex-M4核中断实验实验要求MX相关设置LED设置按键设置光电开关&#xff0c;火焰传感器&#xff0c;人体红外设置UART4设置代码编写结果测试实验要求 使用M4核开发 PF7/PF8/PF9/PF5/PF12/PE15检测中断 要求1&#xff1a;当中断到来时&#xff0c;LED灯状态取反 要求2&a…

EpilepsyGAN:具有隐私保护的合成癫痫脑活动-2021(同26)

EpilepsyGAN: Synthetic Epileptic Brain Activities with Privacy Preservation Abstract 癫痫是一种慢性神经系统疾病&#xff0c;影响全世界6500多万人&#xff0c;表现为反复发作的无端癫痫发作。癫痫发作的不可预测性不仅会降低患者的生活质量&#xff0c;而且还可能危及…

【前端领域】一个好玩好看的罗盘时钟 --- 附详细介绍

唯有热爱&#xff0c;可抵岁月漫长&#xff0c;唯有热爱&#xff0c;不畏世间无常&#xff01; 少年不曾迷茫&#xff0c;展翅飞往神域&#xff0c;坚定初心&#xff0c;踏实行动。 新的一年&#xff0c;收下少年的祝福&#xff0c;一起踏上新道路。 &#x1f4aa;(ง •_•)…

Spring Boot 日志文件

1.日志有什么用&#xff1f; ⽇志是程序的重要组成部分&#xff0c;想象⼀下&#xff0c;如果程序报错了&#xff0c;不让你打开控制台看⽇志&#xff0c;那么你能找到报错的原因吗&#xff1f;答案是否定的&#xff0c;写程序不是买彩票&#xff0c;不能完全靠猜&#xff0c;…

Blender 非线性编辑器

文章目录非线性编辑器介绍动画摄影表/动作编辑器与非线性编辑器NAL非线性编辑器基本操作复制动画片段混合动画片段动画片段N键菜单活动片段栏回放剪辑栏非线性编辑器介绍 1 非线性编辑器是动画制作的一部分&#xff0c;类似于PR的轨道&#xff0c;可以合并多个不同的动画动作 …

【回答问题】ChatGPT上线了!推荐30个以上比较好的构建知识图谱源码

在此列出30个比较好的构建知识图谱的源码&#xff1a; Neo4j AgensGraph JanusGraph AnzoGraph Cayley GraphDB ArangoDB FlockDB OrientDB Redis Graph Virtuoso TigerGraph HyperGraphDB Titan Stardog GraphQL GRAKN.AI AllegroGraph Blazegraph Google Cloud Bigtable Apa…

10四个基本子空间

四个基本子空间 四个基本空间介绍 对于一个 m*n 矩阵 A 来说&#xff0c;以下四个基本空间是其基础。 2.1 四个基本空间的维数与基 还是研究 m*n 的矩阵 A&#xff0c;其四个子空间的基本性质如下: &#xff08;1&#xff09;列空间 之前介绍过列空间的基&#xff0c;设矩…

Go语言 值传递 引用传递 修改集合中的值

分类看一下Go的值传递和引用传递&#xff1a; 值传递&#xff1a;将值传递给函数 /* 引入单测包 */ import ("testing" )func TestSwap(t *testing.T) {x : 100y : 200swap(x, y)println("x:", x)println("y:", y) }/* 定义相互交换值的函数 *…

自己编译docker镜像

有时候官方现在的docker镜像并不能很好地符合自己的需求&#xff0c;我们需要自己定制。以下我主要是在官方mariadb:latest镜像的基础上&#xff0c;做一些定制化的操作如修改容器的编码格式。 /root/.pip目录下有两个文件&#xff1a; Dockerfile的文件内容如下&#xff1a;…

性能优化系列之你是否清楚浏览器的渲染过程?

文章の目录1、浏览器解析 HTML&#xff0c;生成 DOM Tree&#xff08;Parse HTML&#xff09;。2、浏览器解析 CSS&#xff0c;生成 CSSOM&#xff08;CSS Object Model&#xff09; Tree。3、JavaScript 会通过 DOM API 和 CSSOM API 来操作 DOM Tree 和 CSS Rule Tree&#x…

Docker安装Kibana整合Elasticsearch[包含账号密码设置]

文章目录一&#xff1a;拉取Es和Kibana镜像二&#xff1a;创建Es挂载目录2.1&#xff1a;挂载相关配置2.2&#xff1a;开放文件权限&#xff0c;否则后面运行容器会报错三&#xff1a;运行Es容器3.1: 运行参数说明3.2: 运行容器命令3.3: 开放防火墙四&#xff1a;运行Kibana容器…

十四、Kubernetes中pod配置详解、实例

1、概述 在kubernetes中基本所有资源的一级属性都是一样的&#xff0c;主要包含5部分&#xff1a; apiVersion <string> 版本&#xff0c;由kubernetes内部定义&#xff0c;版本号必须可以用 kubectl api-versions 查询到 kind <string> 类型&#xff0c;由kuber…

我辛辛苦苦做了一个月的项目,组长年底用来写了晋升PPT

最近有朋友跟我吐槽&#xff0c;9月10月辛辛苦苦做了一个多月的项目&#xff0c;是一个重点项目&#xff0c;自己还是开发主力&#xff0c;但年底组长用来写了晋升PPT&#xff0c;汇报的时候还写的可圈可点&#xff0c;完全就是他做的样子。 目录 1、我也曾盼望升职加薪 2、结…