java内存模型(jmm)需通过理解规则、编写正确代码并验证行为来掌握,核心是线程间变量的可见性、有序性与原子性;学习重点在于解释典型并发现象、搭建可验证实验环境(如jdk 17/21、禁用jit、jcstress测试)、动手实践三大问题示例,并以happens-before三条关键规则串联分析。

明确JMM的学习目标
不是记住八大原子操作,而是能解释以下现象:
• 为什么两个线程同时改一个int变量,结果可能丢失?
• volatile修饰的boolean flag=true后,另一个线程一定能立刻看到true?
• synchronized块里修改的变量,退出后一定对其他线程可见吗?
• 用Lock代替synchronized时,happens-before关系还成立吗?
搭建可验证的实验环境
必须能亲手跑出并发问题,才能真正信服JMM的存在:
- JDK版本选LTS且支持调试:推荐JDK 17或21(含ZGC、更清晰的JIT日志),避免用过旧版本导致现象不典型
- IDE开启字节码查看:IntelliJ IDEA中安装“Bytecode Viewer”插件,对比加volatile和不加时的字节码差异(特别是getstatic/putstatic前是否有lock指令)
-
禁用JIT优化干扰:运行时加参数
-XX:-TieredStopAtLevel=1 -Xint,强制解释执行,避免重排序被JIT掩盖 - 用jcstress做微基准测试:官方并发压力测试工具,能复现可见性/重排序等微妙问题,比手写while(true)更可靠
聚焦三大问题+对应机制
把JMM拆成可动手的模块,每个模块配一个最小可运行示例:
- 可见性:写一个共享int变量,线程A循环自增,线程B轮询读取——不加volatile时B永远看不到变化;加上后立即可见。观察CPU缓存行刷新效果
- 有序性:构造双重检查单例,去掉volatile时,new对象的三步(分配内存→初始化→赋值给引用)可能重排,导致其他线程拿到未初始化的对象
- 原子性:i++在字节码中是getfield→iconst_1→iadd→putfield四步,用jconsole或arthas attach到正在运行的进程,dump线程栈看中间状态
用happens-before串联所有知识点
这是JMM的“总开关”,不用背八条规则,只需盯住三条最常用:
- 同一个线程内,代码顺序即happens-before顺序(程序顺序规则)
- synchronized解锁操作 happens-before 后续任意线程对该锁的加锁操作(管程锁定规则)
- volatile写 happens-before 后续任意线程对该volatile变量的读(volatile变量规则)
遇到任何并发现象,先画出操作时间线,标出哪些happens-before边存在,再判断结果是否符合预期。
不复杂但容易忽略Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











