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

02 | Java内存模型:看Java如何解决可见性和有序性问题

第一部分:并发理论基础

02 | Java内存模型:看Java如何解决可见性和有序性问题


文章目录

  • 第一部分:并发理论基础
    • 02 | Java内存模型:看Java如何解决可见性和有序性问题
      • 什么是 Java 内存模型?
      • 使用 volatile 的困惑
      • Happens-Before 规则
        • 1. 程序的顺序性规则
        • 2. volatile 变量规则
        • 3. 传递性
        • 4. 管程中锁的规则
        • 5. 线程 start() 规则
        • 6. 线程 join() 规则
      • 被我们忽视的 final
      • 总结
      • 课后思考

上一期我们讲到在并发场景中,因可见性、原子性、有序性导致的问题常常会违背我们的直觉,从而成为并发编程的 Bug 之源。
那我们就先来聊聊如何解决其中的可见性和有序性导致的问题,这也就引出来了今天的主角——Java 内存模型

什么是 Java 内存模型?

你已经知道,导致可见性的原因是缓存,导致有序性的原因是编译优化,那解决可见性、有序性最直接的办法就是禁用缓存和编译优化,但是这样问题虽然解决了,我们程序的性能可就堪忧了

合理的方案应该是按需禁用缓存以及编译优化。那么,如何做到“按需禁用”呢?所以,为了解决可见性和有序性问题,只需要提供给程序员按需禁用缓存和编译优化的方法即可。

Java 内存模型是个很复杂的规范,可以从不同的视角来解读,站在我们这些程序员的视角,本质上可以理解为,Java 内存模型规范了 JVM 如何提供按需禁用缓存和编译优化的方法。具体来说,这些方法包括 volatile、synchronized 和 final 三个关键字,以及六项 Happens-Before 规则,这也正是本期的重点内容

使用 volatile 的困惑

volatile关键字并不是 Java 语言的特产,古老的 C 语言里也有,它最原始的意义就是禁用 CPU 缓存

例如,我们声明一个 volatile 变量 volatile int x = 0,它表达的是:告诉编译器,对这个变量的读写,不能使用 CPU 缓存,必须从内存中读取或者写入。这个语义看上去相当明确,但是在实际使用的时候却会带来困惑。

例如下面的示例代码,假设线程 A 执行 writer() 方法,按照 volatile 语义,会把变量 “v=true” 写入内存;假设线程 B 执行 reader() 方法,同样按照 volatile 语义,线程 B 会从内存中读取变量 v,如果线程 B 看到 “v == true” 时,那么线程 B 看到的变量 x 是多少呢?

直觉上看,应该是 42,那实际应该是多少呢?这个要看 Java 的版本,如果在低于 1.5 版本上运行,x 可能是 42,也有可能是 0;如果在 1.5 以上的版本上运行,x 就是等于 42。

// 以下代码来源于【参考1】 class VolatileExample { int x = 0; volatile boolean v = false; public void writer() { x = 42; v = true; } public void reader() { if (v == true) { // 这里x会是多少呢? } } }

分析一下,为什么 1.5 以前的版本会出现 x = 0 的情况呢?我相信你一定想到了,变量 x 可能被 CPU 缓存而导致可见性问题。这个问题在 1.5 版本已经被圆满解决了。Java 内存模型在 1.5 版本对 volatile 语义进行了增强。怎么增强的呢?答案是一项 Happens-Before 规则。

Happens-Before 规则

Happens-Before 并不是说前面一个操作发生在后续操作的前

http://www.rkmt.cn/news/1533894.html

相关文章:

  • AI编程工具如何解决团队协作四大断点:审查、知识、规范与上下文
  • 深度解析AzurLaneAutoScript:碧蓝航线全自动脚本架构设计与性能优化策略
  • 2020容器技术演进:从隔离机制到云原生操作系统
  • Ubuntu终端效率革命:Terminator分屏工作流实战指南
  • 27-Docker部署Django(上)-从2GB到180MB的镜像瘦身实战
  • EUREKA:面向大模型能力边界的模块化评估框架
  • F★程序安全提取与关系引用技术解析
  • BOxCrete: A Bayesian Optimization Open-Source AI Model for Concrete Strength Forecasting and MixOpt
  • 遗传算法解决医院排班难题:Python+DEAP实战指南
  • 如何在Windows电脑上免费实现AirPlay投屏接收:完整开源方案指南
  • R语言数据结构本质:内存布局、类型契约与性能优化
  • 百度文库文档获取实战指南:高效免费保存解决方案深度解析
  • 3分钟掌握Windows右键菜单管理终极方案:从混乱到高效的完整指南
  • DHT11温湿度传感器驱动全解析:从51单片机到STM32实战指南
  • SQL Server物理连接操作原理与性能优化实战
  • 2026年6月多普勒流量计品牌好评榜:国产力量主导水务与环保场景的技术突围与市场格局 - 仪表品牌榜
  • 长沙水电维修服务推荐、2026正规水电维修公司上门收费标准 - 我叫一
  • 5个步骤构建AI驱动的可视化数据分析平台:Awesome-Dify-Workflow实战指南
  • 人形机器人落地三要素:感知-决策-执行闭环实战解析
  • 贵阳水电维修服务推荐、2026正规水电维修公司上门收费标准 - 我叫一
  • 智慧树自动刷课插件终极指南:5分钟实现高效学习
  • Bass-Serre树与EZ结构在群论中的分离技术解析
  • 2026年成都启闭机厂家怎么选?实地走访与行业分析报告 - 优质品牌商家
  • Ray Ozzie软件工程思想:从协作系统到云原生的架构启示
  • σ-VQE算法:量子变分本征求解器的创新与应用
  • 2026年6月多声道超声波流量计品牌好评榜:技术迭代下的国产力量与市场格局重构 - 仪表品牌榜
  • Python新手必踩的坑:为什么你的file.read_lines()总是报错?手把手教你用对readlines()
  • Ubuntu更新提醒关闭指南:分层控制不牺牲安全
  • Linux入门实战地图:从SSH登录到WordPress部署的四大核心场景
  • 南京水电维修服务推荐、2026正规水电维修公司上门收费标准 - 我叫一