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读

字节码层面

内存屏障是什么

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Java语言】遍历List元素时删除集合中的元素

目录 前言 实现方式 1.普通实现 1.1 使用【for循环】 方式 1.2 使用【迭代器】方式 2.jdk1.8新增功能实现 2.1 使用【lambda表达式】方式 2.2 使用【stream流】方式 注意事项 1. 使用【for循环】 方式 2. 不能使用增强for遍历修改元素 总结 前言 分享几种从List中移…

程序语言设计

一、程序设计语言及其构成 1.程序设计语言 2.高级程序设计语言划分 3.常见的高级程序语言 4.标记语言 5.程序设计语言的构成 二、表达式 表达式的类型及转换规则 三、传值和传址调用 1.数据类型 2.传值和传址调用 四、语言处理程序 1.语言处理程序 语言处理程序&#xff1…

【JS】浅谈浅拷贝与深拷贝

浅拷贝与深拷贝 前言一、浅拷贝?1.1是什么?1.2做什么?1.3为什么使用?1.4实现方式?1.5 应用场景? 二、深拷贝?2.1是什么?2.2做什么?2.3为什么使用?2.4实现方式…

成都产业园排名出炉!金牛区这个园区成数字产业聚集地

近日,成都产业园排名榜单正式发布,可以看出金牛区成数字产业聚集地,其中,备受瞩目的国际数字影像产业园荣登榜首。这一排名不仅彰显了国际数字影像产业园在数字产业领域的卓越表现,更凸显了成都作为西部重要城市在科技…

51单片机系列-单片机定时器

🌈个人主页:会编辑的果子君 💫个人格言:“成为自己未来的主人~” 软件延时的缺点 延时过程中,CPU时间被占用,无法进行其他任务,导致系统效率降低,延时时间越长,该缺点就越明显&…

HBuilder发行微信小程序

首先需要完善mainifest.json中的基本配置 这个需要组测dcloud才可以获取,注册后点击重新获取就可以。 然后发行前还需要完成dcloud的信息,这个他会给你网址 点击连接完成信息填写就可以了 然后就可以发行了。 发行成功后会自动跳转微信小程序&#xff…

day02vue学习

day02 一、今日学习目标 1.指令补充 指令修饰符v-bind对样式增强的操作v-model应用于其他表单元素 2.computed计算属性 基础语法计算属性vs方法计算属性的完整写法成绩案例 3.watch侦听器 基础写法完整写法 4.综合案例 (演示) 渲染 / 删除 / 修…

Flutter第四弹:Flutter图形渲染性能

目标: 1)Flutter图形渲染性能能够媲美原生? 2)Flutter性能优于React Native? 一、Flutter图形渲染原理 1.1 Flutter图形渲染原理 Flutter直接调用Skia。 Flutter不使用WebView,也不使用操作系统的原生控件,而是…

如何深度学习

信息爆炸时代,诞生了很多新的学习方式,非常轻松就能掌握知识,比如,每天听一本书,半个小时就能学习一本书的精华,比如订阅名家专栏或者课程,在不长的时间内内就能学到很多知识。 很多人认为这样…

jenkins 使用k8s插件连接k8s集群

jenkins 安装k8s 插件 配置k8s节点 填写k8s 配置信息 生成秘钥 在服务器上面 查看地址 Kubernetes 服务证书 key cat /root/..kube/config 查看秘钥 对秘钥进行base64 位 加密 echo "秘钥内容" | base64 -d -----BEGIN CERTIFICATE----- MIIDITCCAgmgAwIB…

【node】模块化与包(二)

1、模块化的基本概念 模块化是指解决一个复杂的问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换的单元。 (1)模块化的优点 遵循固定规则,把大文件拆分成对立并相互依赖…

【Axure高保真原型】下拉列表切换图表

今天和大家分享通过下拉列表动态切换统计图表的原型模板,我们可以通过下拉列表选择要显示的图表,包括柱状图、条形图、饼图、环形图、折线图、曲线图、面积图、阶梯图、雷达图;而且图表数据可以在左侧表格中动态维护,包括增加修改…

数码管的动态显示(二)

1.原理 这个十六进制是右边的dp为高位。 数码管的动态显示,在第一个计数周期显示个位,在第二个周期显示十位,在第三个周期显示百位由于人眼的视觉和数码管的特性,感觉就是显示了234,每个数码管的显示需要从输入的数据里…

科普编程中 宿主环境(host environment) 基础概念

我们来说说 宿主环境 首先 什么是宿主环境? 宿主环境 (host environment) 意思就是 程序运行所必须的依赖环境 安卓和IOS 系统 就是两种完全不同的宿主环境 总所周知 微信版的安卓App 在苹果中是无法运行的 所以说 Android 是安卓软件的宿主环境 离开了这个宿主环…

ECharts饼图图例消失踩的坑

在使用Echarts的饼图时,当时做法是在图例数小于8时显示全部的图例,在大于8的时候显示前8个图例。于是用了两种不同的方式处理。导致出现切换时间后图例不显示的情况。 错误过程: 在进行图例生成时采用了两种不同的方式: ①如果…

Linux内核编译(版本6.0以及版本v0.01)并用qemu驱动

系统环境: ubuntu-22.04.1-desktop-amd64 目标平台: x86 i386 内核版本: linux-6.0.1 linux-0.0.1 环境配置 修改root密码 sudo passwd 修改软件源(非必要) vmtools安装(实现win-linux软件互传) 安装一些必须的软件&…

代码随想录算法训练营第25天|216.组和总和三、17.电话号码的字母组合

目录 一、力扣216.组合总和三1.1 题目1.2 思路1.3 代码 二、力扣17.电话号码的字母组合2.1 题目2.2 思路2.3 代码 一、力扣216.组合总和三 1.1 题目 1.2 思路 自己的想法:和总和问题思路类似,回溯法。 (1)k个数的组合&#xff0…

如何查看mnist数据集的图片

import numpy as np import matplotlib.pyplot as pltdef read_mnist_images(filename):with open(filename, rb) as f:# 读取魔术数字、图像数量、行数、列数magic_number int.from_bytes(f.read(4), big)number_of_images int.from_bytes(f.read(4), big)rows int.from_by…

《详解:鸿蒙NEXT开发核心技术》

我们现在都知道鸿蒙作为一个国产的全栈自研系统,经过国家主推后。已经引起人们很大的关注,其中作为开发者来说;许多一线大厂已经与其华为鸿蒙展开原生应用的合作了,目前了解到已经有200家。而之后出现了很多的高薪鸿蒙开发岗位&am…

ThreeJs 射线拾取不准确设置

欢迎关注进来点个关注; 关注获取更多咨询!关注获取答案! 1、效果图如下: 2、问题描述:点击一开始无法获取当前的位置,官方推荐直接使用 mouseClick.x = (event.offsetX / window.innderWidth) * 2 - 1; mouseClick.y = -(event.offsetY / window.innderHeight) * 2 + 1;…