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

JMM 浅析

什么是JMM?

JMM 即 Java 内存模型 Java Memory Model 简称 JMM。
本身是一种抽象的概念,并不真实存在,它仅仅描述的是一组约定或规范,通过这组规范定义了程序中(尤其是在多线程中)各个变量的读写访问方式并决定一个线程对共享变量的写入何时以及如何对另一个线程可见,关键技术点都是围绕多线程的原子性、可见性、有序性展开的。

JMM 能干嘛?
  • 通过JMM来实现内存和内存之间的抽象关系
  • 屏蔽各个硬件平台和操作系统的内存访问差异 以实现让 Java 程序在各种平台下都能达到一致的内存访问效果

可见性

在这里插入图片描述
在这里插入图片描述

原子性

是指一个操作是不能被打断的,在多线程环境下面操作不能被其他线程干扰

有序性

在这里插入图片描述
处理器在进行重排序的时候必须要考虑指令之间的数据依赖性
多线程环境中线程交替执行,由于编译器优化重排的存在,两个线程间中使用的变量能否保证一致性是无法确定的,结果无法预测。

JMM规范下 多线程对变量的读写过程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

JMM 规范下 happens-before 原则

在 JVM 中,如果一个操作执行的结果需要对另一个操作保持可见性,或者代码重排序,那么这两个操作之间必须存在 happens-before 原则,即存在逻辑上的先后关系

在这里插入图片描述

在这里插入图片描述

happers-before 8条规则

在这里插入图片描述

1. 次序规则

一个线程内按照代码顺序,写字前面的操作先行发生于写在后面的操作

2. 锁定规则

一个 unlock 操作先行发生于(时间上的先后)后面对同一个锁的 lock 操作

3. volatile 变量规则

对一个 volatile 变量的写操作先行发生于后面对这个变量的读操作,前面的写对后面的读是可见的(同样指时间上的先后)

4. 传递规则

如果 A 操作先行发生于 B, B 操作先行发生于操作 C ,那么一定有 A 操作先行发生于 C 操作

5. 线程启动规则

Thread 对象的 start() 方法先行发生于这个线程对象的所有动作

6. 线程中断规则

对线程 interrupt() 方法的调用优先发生于被中断线程的代码检测到中断事件的发生
可以通过 Thread.interrupt() 方法来检测到是否发生过中断
也就是说可以先调用 interrupt() 方法来先设置过中断标志位,才能检测到中断发送

7. 线程终止规则

线程中的所有操作都先行发生于对此线程的终止检测,我们可以通过 isAlive() 等手段检测线程是否已经终止执行

8. 对象终结规则

一个对象的初始化完成(构造函数执行结束)先行发生于它的 finalize() 方法的开始

在这里插入图片描述

volatile 特点:可见    有序  不能保证原子!!!!!!!

volatile 的内存语义:
在这里插入图片描述

volatile 为什么可以保证可见性和有序性? --------- 内存屏障 Memory Barrier

在这里插入图片描述

内存屏障是什么?

在这里插入图片描述

四大屏障:

在这里插入图片描述

happens-before 之 volatile 规则
在这里插入图片描述
在这里插入图片描述
volatile 保证不同线程对某个变量完成操作之后结果及时可见,即该共享变量一旦改变所有线程立即可见

volatile 变量的读写过程:

在这里插入图片描述
在这里插入图片描述

volatile 不能保证原子性!!!!!!!

在这里插入图片描述

指令重排序

在这里插入图片描述

具体的内存屏障插入规则:

在这里插入图片描述

在这里插入图片描述

volatile 最佳使用场景:

单一赋值可以,but 复合运算赋值不可以(i++ 之类)

volatile int a = 10;
volatile boolean flag = true;

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

在这里插入图片描述

开销较低的读、写锁策略

在这里插入图片描述

DCL 双端锁的发布

单例模式应用,传统的双重检查单例模式,在多线程的情况下,有可能会发生变量刚初始化 但是没复制就被拿去使用的情况(实例化一个对象的时候分多个步骤执行,包括分配内存空间、初始化对象、将对象指向分配的内存空间,而某些编译器为了性能原因会将第二步和第三步进行重排序,这样某个线程就又可能会获得一个未完全初始化的对象),使用 volatile 修饰的变量可以防止这种情况发生

volatile 小结:

在这里插入图片描述

http://www.xdnf.cn/news/18941.html

相关文章:

  • StandardScaler()进行0,1标准化时fit_transform与transform的区别
  • HTML的form表单
  • 子串:和为K的子数组
  • 记一个Mudbus TCP 帮助类
  • from中烟科技翼支付 面试题1
  • 财报出炉,李宁也被“靠边站”了
  • 摄像头模块的技术原理
  • WeakAuras Lua Script (My Version)
  • 【Lua】题目小练11
  • 红黑树下探玄机:C++ setmultiset 的幕后之旅
  • 无线网络中的Duration字段计算:原理、机制与实现
  • 深入了解linux系统—— 线程封装
  • 【prism】Prism 弹窗在 ViewModel 中控制大小的实践总结
  • 视觉工具:文字显示、图像标注与多模板匹配
  • 「大模型学习」(15)Prompt Tuning → P-Tuning v1 → P-Tuning v2
  • STM32G4 SVPWM VF开环强拖电机
  • 两周年创作纪念,忆笑傲江湖岁月
  • 【生产实践】局域网多服务器多用户SSH登录批量测试(附完整shell脚本)
  • Linux-服务器初始化
  • 【智能化解决方案】大模型智能推荐选型系统方案设计
  • week5-[字符数组]查找
  • GD32VW553-IOT开发板测评 搭建环境到电灯(QA分享)
  • Element中table组件(el-table)右侧滚动条空白占位gutter处理
  • vue3和react的异同点
  • Tesseract OCR之基线拟合和单词检测
  • 从0开始学习Java+AI知识点总结-26.web实战(Springboot原理)
  • Linux服务器安全配置与NTP时间同步
  • 【Python系列】Flask 和 FastAPI对比
  • 【深度学习新浪潮】SAM 2实战:Meta新一代视频分割模型的实时应用与Python实现
  • Boris FX Samplitude Suite 2025.0.0 音频录制/编辑和母带处理