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

JUC并发总结二

大纲

6.volatile如何保证可见性

7.volatile的原理(Lock前缀指令 + 内存屏障)

8.双重检查单例模式的volatile优化

9.synchronized关键字的原理

10.wait()与notify()的底层原理

11.Atomic原子类中的CAS无锁化原理

12.LongAdder的分段CAS优化多线程自旋

6.volatile如何保证可见性

(1)volatile型变量的特殊规则

volatile变量对所有线程都是立即可见的:对volatile变量的所有写操作都能立刻反映到其他线程之中,volatile变量在各个线程的工作内存中是不存在数据不一致性的问题。从物理存储的角度看,各个线程的工作内存中,volatile变量也可能存在不一致。但由于各个工作线程在每次使用volatile变量之前都要先刷新其值,于是执行引擎便看不到不一致的情况,因此可以认为不存在不一致的问题。

volatile变量是禁止指令重排序优化的:指令重排序是指CPU将多条指令,不按程序规定的顺序,分开发送给各个相应的电路单元进行处理。可见,volatile型变量的特殊规则就规定了volatile变量对所有线程立即可见。

(2)volatile如何保证可见性

普通变量和volatile变量的区别是:volatile保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。也就是volatile保证了多线程操作时变量的可见性,而普通变量则不能保证。

图片

如果flag变量是加了volatile关键字,那么当线程1通过assign操作将flag = 1写回工作内存时,会立即执行store和write操作将flag = 1同步到主内存。同时还会让线程2的工作内存中的flag变量的缓存过期,这样当线程2后续从工作内存里读取flag变量的值时,发现缓存已经过期就会重新从主内存中加载flag = 1的值。所以通过volatile关键字可以实现这样的效果:当一个线程修改了变量值,其他线程可以马上感知这个变量值。

(3)volatile不能保证原子性的字节码解释

比如对volatile变量n进行自增的方法虽然只有一行代码,但用javap反编译可知由4条字节码指令构成。当get_field指令把n的值取到操作栈顶时,volatile保证了n的值此时是最新的。但线程1执行iconst_1、iadd这些指令时,线程2可能已经把n的值改变了。于是此时线程1的操作栈顶的n值,就变成了过期数据,所以线程1执行put_field指令后就会把较小的n值同步回主内存中。

严格来说,volatile并不是轻量级的锁或者是轻量级同步机制。因为对于n++这样的基本操作,加了volatile关键字也无法保证原子性。而锁和同步机制,如synchonized或者lock是可以保证原子性的。

(4)volatile如何保证有序性

Happens-Before规则的volatile变量规则:程序中的代码如果满足上面这8条规则,就一定会保证指令的顺序。但是如果没满足上面的8条规则,那么就可能会出现指令重排。如对一个volatile变量的写操作先行发生于后面对这个volatile变量的读操作。

volatile型变量的特殊规则:volatile型变量会禁止指令重排序优化。在有序性问题的例子一中,使用volatile修饰flag能禁止重排序避免逻辑异常。在有序性问题的例子二中,使用volatile修饰instance能禁止重排序避免异常。

7.volatile的原理(Lock前缀指令 + 内存屏障)

(1)Lock前缀指令 + MESI实现可见性

如果对volatile关键字修饰的变量执行写操作,那么JVM就会向CPU发送一条Lock前缀指令,将这个变量所在的缓存行数据写回到主内存中。同时根据MESI缓存一致性协议,各个CPU会通过嗅探在总线上传播的数据,来检查该变量的缓存值是否过期。如果发现过期,CPU就会将该变量所在的缓存行设置成无效状态。后续当这个CPU要读取该变量时,就会从主内存中加载最新的数据。

所以Lock前缀指令 + MESI缓存一致性协议实现了volatile型变量的可见性。Lock前缀指令会引起将volatile型变量所在的缓存行数据写回到主内存,MESI缓存一致性协议可让CPU检查出哪些缓存被修改,同时令缓存失效。

(2)通过内存屏障实现禁止指令重排序

通过内存屏障来禁止某些指令重排序:加了volatile关键字的变量,可以保证前后的一些代码不会被指令重排。那么这个是如何做到的呢?volatille是如何保证有序性的呢?为了保证内存可见性,J


文章转载自:

http://VzVkliEy.dwyyf.cn
http://ONSE9Ptx.dwyyf.cn
http://w68aCDcw.dwyyf.cn
http://TFDSqxbG.dwyyf.cn
http://hrqzIj9L.dwyyf.cn
http://1enGGdR8.dwyyf.cn
http://TdwG6cFu.dwyyf.cn
http://hPkWdf5D.dwyyf.cn
http://kxuQn33Y.dwyyf.cn
http://eo6rajlx.dwyyf.cn
http://nwkGmGCn.dwyyf.cn
http://oNwkhgUA.dwyyf.cn
http://XXlJg6dX.dwyyf.cn
http://lYj4B5EH.dwyyf.cn
http://5WMIF7wr.dwyyf.cn
http://pzTyFVjc.dwyyf.cn
http://1oSPxIxn.dwyyf.cn
http://Lr9jxmmk.dwyyf.cn
http://aeWgxIYh.dwyyf.cn
http://hUuVyZrP.dwyyf.cn
http://MOLcdZjD.dwyyf.cn
http://OXE6GTHB.dwyyf.cn
http://SbA6wD8H.dwyyf.cn
http://Tny4Hao2.dwyyf.cn
http://Npy8YcCL.dwyyf.cn
http://R1vChUu2.dwyyf.cn
http://TEHMw0O0.dwyyf.cn
http://AdECsVa3.dwyyf.cn
http://u6FNo6ab.dwyyf.cn
http://gdm3iJg8.dwyyf.cn
http://www.dtcms.com/a/28770.html

相关文章:

  • WEB前端将指定DOM生成图片并下载最佳实践(html2canvas)
  • 跟着AI学vue第六章
  • 以ChatGPT为例解析大模型背后的技术
  • Nginx 请求超时
  • uniapp中引入Vant Weapp的保姆级教学(包含错误处理)
  • CV -- 基于GPU版CUDA环境+Pycharm YOLOv8 目标检测
  • 将Google文档导入WordPress:简单实用的几种方法
  • Linux的指令与热键
  • 《动手学机器人学》笔记
  • 软件著作权申请流程详解:从准备到登记的完整指南
  • MAC快速本地部署Deepseek (win也可以)
  • 【Elasticsearch】如何获取一致的评分
  • 装修流程图: 装修前准备 → 设计阶段 → 施工阶段 → 安装阶段 → 收尾阶段 → 入住
  • 小米路由器 AX3000T 降级后无法正常使用,解决办法
  • Linux基本指令(二)
  • QML double浮点数取小数点后某几位【去尾法】
  • 【Linux基础八】计算机体系结构(冯诺依曼和操作系统)
  • 【嵌入式常用工具】Srecord使用
  • 探索显著性检测中语义信息的高效模型
  • FlutterAssetsGenerator插件的使用
  • sql server 从库创建的用户名登录后访问提示数据库无权限
  • YOLO11学习
  • 神经网络八股(2)
  • 为啥vue3设计不直接用toRefs,而是reactive+toRefs
  • 10、k8s对外服务之ingress
  • [数据结构]单链表详解
  • 【核心算法篇十六】《DeepSeek强化学习:MuZero算法核心解析》
  • 用大内存主机下载Visual Studio
  • day17-后端Web原理——SpringBoot原理
  • 解决 LeetCode 串联所有单词的子串问题