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

java内存模型(JMM)

一、前言(多核并发缓存架构)

说起java并发内存模型,首先了解一下多核并发缓存架构,就是我们服务器的cpu和主内存之间,因为2者运算速度有较大差距,所以在cpu与主内存之间,有一道cup缓存,cpu通过cpu缓存读取数据,进而让cpu发挥出性能优势

二、JMM内存模型

java内存模型和和cpu缓存模型类似,是基于cpu缓存模型建立的

三、示例说明

为了便于理解,我们结合一段代码示例来看下

结果1:22行代码改了flag,但是可以看到结果并没有打印出"线程1感知到flag变成true",说明线程t1里并没有感知到flag变成true

那么我们接下来将flag加上volatile再尝试运行,

结果2:我们发现加上volatile修饰后,打印出了"线程1感知到flag变成true",说明线程t1感知到flag变成true

通过结果1,可以说明,线程内部确实是读取线程内部的数据副本进行代码处理

通过结果2,则说明可以通过volatile来实现共享变量的可见性(并发编程的3大特性:可见性、有序性、原子性

好的,那么volatile是怎么实现可见性的呢?那就需要结合java的JMM数据原子操作指令以及缓存一致性协议来一起看下

JMM数据原子操作:

read(读取):从主内存读取数据
load(载入):将主内存读取到的数据写入工作内存
use(使用):从工作内存读取数据来计算
assign(赋值):将计算好的值重新赋值到工作内存中
store(存储):将工作内存数据写入主内存
write(写入):将store过去的变量值赋值给主内存中的变量
lock(锁定):将主内存变量加锁,标识为线程独占状态
unlock(解锁):将主内存变量解锁,解锁后其他线程可以锁定该变量

缓存一致性协议(MESI)
多个cpu从主内存读取同一个数据到各自的高速缓存,当其中某个cpu修改了缓存里
的数据,该数据会马上同步回主内存,其它cpu通过总线嗅探机制可以感知到数据的
变化从而将自己缓存里的数据失效
缓存加锁
缓存锁的核心机制是基于缓存一致性协议来实现的,一个处理器的缓存回写到内存会
导致其他处理器的缓存无效,IA-32和Intel64处理器使用MESI实现缓存一致性协议

好的,那其实上述代码对应的JMM原子操作流程如图

结合图中箭头,大家可以知道主线程是获取并修改flag的值的,那线程t1使用flag变量的时候,是通过总线嗅探机制(图中绿色)发现flag被修改了,接下来会把自己的工作内存中的flag变量副本失效,从而从主内存的flag变量重新read、load到线程t1的工作内存中。这就是volatile的可见性原理。

好的,那么大家还记得volatile还保证了有序性,这个是怎么实现的呢?

首先java底层是有指令重排序的,就是在不影响单线程执行结果的前提下,计算机为了发挥最大新能,会对机器指令重新排序优化!具体原则是as-if-serial与happens-before(具体不展开了),大家简单理解一下

1、可以重排序:

int a =1;

int b=2;

这2行代码执行顺序不影响结果,所以可以重排序

2、不可以重排序:

int a = 1;

int b = a;

显然,执行顺序影响结果,所以不可以重排序

那关键就来了,既然有可能发生重排序,volatile就是通过解决重排序来保障有序性的,这个实现过程叫做内存屏障,对应规范如下

屏障类型指令说明
LoadLoadLoad1;LoadLoad;Load2保证load1的读取操作在load2及后续读取操作之前执行
StoreStoreStoreStoreStore;Store2在store2及其后的写操作执行前,保证store1的写操作已刷新到主内存
LoadStoreLoad1; LoadStore; Store2在stroe2及其后的写操作执行前,保证load1的读操作已读取结束
StoreLoadStore1;StoreLoad:Load2保证store1的写操作已刷新到主内存之后,load2及其后的读操作才能执行

java规定了volatile需要实现的内存屏障,我们举个例子说明一下

int volatile a =1;

int b = a;

则对应的屏障:

StoreStore屏障
a=1://volatile写,a为volatile变量
StoreLoad屏障
b =a;//volatile读
LoadLoad屏障
LoadStore屏障

这样保障了代码的执行顺序,进而保障有序性

http://www.jsqmd.com/news/793998/

相关文章:

  • 嵌入式开发:从汇编到C语言的高效迁移与优化
  • AI+运维提效,ssl-cert-monitoring(SSL证书监控系统)2.0修复bug及新增功能说明
  • 软件设计原则之OCP开闭原则
  • 2026廊坊硅酸铝柔性包裹,防火专业厂家这样选
  • ARM虚拟化关键寄存器HIFAR与HMAIR详解
  • 终极指南:如何用Vue-Fabric-Editor解决轻量级图片编辑需求
  • 从EE Times标题竞赛看工程师文化:技术幽默如何驱动社区活力
  • 基于CMSIS和USB的嵌入式数据记录器开发指南
  • 高校普法系统|基于SSM高校普法系统(源码+数据库+文档)
  • 在Node.js后端服务中集成多模型API以提升应用灵活性
  • 学Simulink——基于储能系统参与电网一次调频的下垂控制仿真示例
  • TTS推理优化:低精度计算与硬件协同设计实践
  • 从零开始,在 Simulink 中搭建主电路,设计 SPWM 信号发生器,并观察滤波前后的波形变化
  • mp = collections.defaultdict(nums)mp = dict()有啥区别
  • ARM TLB维护指令TLBIP RVAE2详解与优化实践
  • AI编程入门指南:从提示词工程到实战工具配置
  • 模型驱动开发与软件产品线工程实践指南
  • 学生成绩管理系统(SSM框架)环境搭建与运行总结
  • AI模型轻量化部署实战:从模型压缩到边缘计算优化
  • 无监督在线视频稳定化技术:混合框架与实时优化
  • OpenViking:云原生AI场景下的高性能可观测性数据采集框架深度解析
  • VS Code + Claude Code 与 Codex 插件接入其他大模型详细教程
  • 硬件敏捷开发转型:MAHD框架实践与Altium工具链应用
  • 哔哩下载姬完整指南:轻松获取B站高清视频的3步解决方案
  • PCI总线调试挑战与MSO解决方案
  • 你还在用Airflow调度AI任务?奇点大会披露:下一代数据管道已淘汰编排范式——转向意图驱动的语义执行层(附对比压测数据:吞吐提升4.7x,Failover缩短至87ms)
  • 大跨度异型电动挡烟垂壁技术研发与工程应用研究
  • Godot MCP服务器:AI助手与游戏开发工作流的高效集成方案
  • Arm® Lifecycle Manager (LCM) 技术解析与应用
  • 备战蓝桥杯国赛【Day 8】