Volatile与JMM

被Volatile修饰的变量有两大特点

可见性

有序性(禁重排)

如何保证的?内存屏障

Volatile的内存语义

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

当读一个Volatile变量的时候,JMM会把本地内存置为无效,重新回到主内存中读取最新共享变量。

内存屏障

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

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

看到写屏障:把这个指令之前的全部写回主内存

看到读屏障:保证了读取到的数据都是最新的

写屏障(Store Barrier)

写指令之后插入

读屏障(Load Barrier)

读指令之前插入

源码分析

度屏障

写屏障

读写混合

Unsafe.class 一定会对应 Unsafe.java

C++代码

细分4种

禁重排

其他情况随便编译器怎么重排序都行

Volatile插入读屏障示意图

Volatile插入写屏障示意图

保证可见性

案例1

结果

程序无法结束

原因:

案例2

将变量声明为volatile

结果

程序正常结束,灯灭了

volatile变量的读写过程

t1线程:

1.先从主内存中读取到自己的工作内存

2.然后use,使用这个变量,当前就一直在while循环里

这里切回main线程看:

1.先从主内存中读取到自己的工作内存

2.然后use,使用这个变量

3.传给cpu,把变量修改为false后,赋值写回工作内存

4.main线程准备把修改写回主内存了,这步要加锁,因为其他线程可能也在往回写,会发生线程安全问题,不就乱了。所以这步一定会加锁的

5.加锁后会清空工作内存中的值,也就是说其他线程手中持有的那份会作废掉,请他们再重新从主内存中重读一份或者重新赋值。

6.此时main线程写完了,立刻解锁,

这里切回t1线程看:

此时工作内存中的变量已经作废了,重新从主内存中拉取最新值为false

t1线程while循环退出

程序结束。

没有原子性

案例1

正常情况:

10个线程 操作1000次 应该是1w

结果:

案例2

此时将变量修改为volatile,同时去除Synchronized关键字

结果:

volatile不具备原子性 不等于1w

读取和赋值一个普通变量的情况

不保证原子性

number++这个操作在java代码看只有一行,但底层其实有3步

1.数据加载

2.数据计算

3.数据赋值

虽然读取到的数据都输最新的,但是写操作可能会出现丢失问题,无法保证原子性。

加了Synchronized关键字的情况

线程A加锁把5改成6,此时线程B原先读的5作废,重新读到6,+1改成7,结果正确。

不加Synchronized关键字的情况

线程B的操作直接作废,比如读到了5然后+1,但还没来得及写,线程A先一步完成,直接把线程B的操作全部作废,产生了写丢失,线程提前结束。

number++字节码分析

原子性:是指一个操作不能被中断,就算在多线程的环境下,也不应该受到其他线程的影响。

建议

指令禁重排

案例1

这里需要加入volatile禁止指令重排序

否则在多线程环境下,i=2和flag=true没有数据依赖性有可能交换顺序,read方法的结果就不可控了

volatile日常使用场景

DCL双端锁单例写法

隐患位置代码:

单线程环境下:

多线程环境下:

不加volatile

总结

可见性

volatile写

volatile读

字节码层面

内存屏障是什么

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

五子棋小游戏(sut实验报告)

实验目的 实现人与人或人与电脑进行五子棋对弈 实验内容 启动游戏,显示游戏参数设置界面,用户输入参数后进入游戏界面,显示棋盘及双方博弈过程,游戏过程中可选择退出游戏。判定一方获胜后结束本局游戏,可选择继续下…

案例分析篇09:Web架构设计相关20个考点(7~11)(2024年软考高级系统架构设计师冲刺知识点总结)

专栏系列文章推荐: 2024高级系统架构设计师备考资料(高频考点&真题&经验)https://blog.csdn.net/seeker1994/category_12593400.html 【历年案例分析真题考点汇总】与【专栏文章案例分析高频考点目录】(2024年软考高级系统架构设计师冲刺知识点总结-案例分析篇-…

【单片机毕业设计7-基于stm32c8t6的智能温室大棚系统】

【单片机毕业设计7-基于stm32c8t6的智能温室大棚系统】 前言一、功能介绍二、硬件部分三、软件部分总结 前言 🔥这里是小殷学长,单片机毕业设计篇7基于stm32的智能衣柜系统 🧿创作不易,拒绝白嫖可私 一、功能介绍 ---------------…

Pytorch实战01——CIAR10数据集

目录 1、model.py文件 (预训练的模型) 2、train.py文件(会产生训练好的.th文件) 3、predict.py文件(预测文件) 4、结果展示: 1、model.py文件 (预训练的模型) impor…

分布式搜索elasticsearch(1)

1.初识elasticsearch 1.1.了解ES 1.1.1.elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容 例如: 在GitHub搜索代码 在电商网站搜索商品 在百度搜索答案…

识别恶意IP地址的有效方法

在互联网的环境中,恶意IP地址可能会对网络安全造成严重威胁,例如发起网络攻击、传播恶意软件等。因此,识别恶意IP地址是保护网络安全的重要一环。IP数据云将探讨一些有效的方法来识别恶意IP地址。 IP地址查询:https://www.ipdata…

RPC基础知识回顾

RPC基础知识回顾 1、先认识一下大家熟悉的HTTP 大家都了解HTTP吧。相信项目中也用过一些。 比如: JDK自带的老旧的HttpURLConnection,封装写的很累,java8之前基于HTTP1.0。在java9开始支持Http2.0Spring的其中RestTemplate都是基于HTTP/1.1的请求。最新的还有Sp…

OceanBase中binlog service 功能的试用

OBLogProxy简介 OBLogProxy即OceanBase的增量日志代理服务,它可与OceanBase建立连接并读取增量日志,从而为下游服务提供了变更数据捕获(CDC)的功能。 关于OBLogProxy的详尽介绍与具体的安装指引,您可以参考这篇官方OB…

离散系统描述模型及其转换

离散系统描述模型及其转换 常用离散模型 \textbf{常用离散模型} 常用离散模型系统传递函数模型 t f \bf{tf} tf零-极点增益模型 z p k \bf{zpk} zpk极点留数模型 r p k \bf{rpk} rpk二次分式模型 s o s \bf{sos} sos状态变量模型 s s \bf{ss} ss 例题 常用离散模型 \textbf{常用…

Arrays.asList转换为List集合后使用add方法抛出UnsupportedOperationException

问题场景: 将String[] 数组转为 List集合,后对list集合进行添加删除报UnsupportedOperationException 百度原因: Arrays.asList返回的集合不支持元素的添加和删除(不支持add、addAll、remove方法),否则抛出…

nginx实时流量拷贝ngx_http_mirror_module

参考: Module ngx_http_mirror_module Nginx流量拷贝ngx_http_mirror_module模块使用方法详解 ngx_http_mirror_module用于实时流量拷贝 请求一个接口,想实时拷贝这个请求转发到自己的服务上,可以使用ngx_http_mirror_module模块。 官网好像…

Java Web实战(四)Web后端之MyBatis-基础用法详解

文章目录 1. 使用MyBatis1-1. JDBC介绍1-2. 数据库连接池1-3. Lombook 2. mybatis 基础2-2. CURD操作2-2-1. delete 操作2-2-2. 预编译sql2-2-3. 插入语句2-2-4. XML-SQL2-2-5. insert主键回显 2-3. 查询语句 3. 动态SQL3-1. <if> MyBatis是一款优秀的 持久层 框架&#…