深入浅出Java内存模型(JMM)

深入浅出Java内存模型(JMM)

一、JMM是啥?

Java内存模型(JMM)就像多线程世界的交通规则

  • 作用:定义线程如何与内存交互,防止"数据车祸"
  • 核心问题 :解决多线程的可见性有序性原子性问题
  • 类比
    • 内存:共享的快递仓库
    • 线程:搬运工人
    • JMM规则:仓库的存取管理制度

二、三大核心问题

1. 可见性问题

java 复制代码
// 线程A
flag = true;  // 写操作

// 线程B
while(!flag); // 可能永远死循环!

问题 :线程A改了flag,线程B看不见
解决 :用volatilesynchronized

2. 有序性问题

java 复制代码
// 代码顺序
int a = 1;
int b = 2;

// 实际执行可能变成:
int b = 2;
int a = 1;

问题 :编译器/CPU会优化指令顺序(重排序)
解决 :用volatilefinal

3. 原子性问题

java 复制代码
count++; // 实际包含3步操作:读→改→写

问题 :多线程同时操作会导致数据错误
解决 :用synchronizedAtomicInteger

三、JMM关键概念

1. 主内存 vs 工作内存

graph LR 主内存 -->|读取| 线程A工作内存 主内存 -->|读取| 线程B工作内存 线程A工作内存 -->|写入| 主内存 线程B工作内存 -->|写入| 主内存
  • 主内存:所有线程共享(相当于仓库)
  • 工作内存:每个线程私有(相当于工人的手推车)

2. happens-before原则(重点!)

JMM规定的操作先后保证规则

  1. 程序顺序规则:同一线程内,代码顺序优先
  2. 锁规则:解锁操作先于后续加锁操作
  3. volatile规则:写操作先于后续读操作
  4. 传递性:A先于B,B先于C → A先于C

示例

java 复制代码
// 线程A
x = 1;          // 操作1
volatileFlag = true; // 操作2(volatile写)

// 线程B
if(volatileFlag) {   // 操作3(volatile读)
    print(x);    // 保证看到x=1!
}

四、volatile关键字

1. 两大特性

  • 可见性:写操作立即刷新到主内存
  • 禁止重排序:优化屏障

2. 底层实现

java 复制代码
// Java代码
volatile boolean flag = false;

// 对应汇编指令(带lock前缀)
0x01a3de24: lock addl $0x0,(%esp);

3. 使用场景

  • 状态标志位(如volatile boolean running
  • 单例模式双重检查锁定
java 复制代码
class Singleton {
    private static volatile Singleton instance;
    
    static Singleton getInstance() {
        if (instance == null) {
            synchronized(Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

五、synchronized机制

1. 内存语义

  • 进入同步块:清空工作内存,从主内存重新加载
  • 退出同步块:将工作内存写回主内存

2. 锁升级过程

graph LR 无锁 --> 偏向锁 --> 轻量级锁 --> 重量级锁
  • 偏向锁:只有一个线程访问时生效
  • 轻量级锁:少量线程竞争时用CAS自旋
  • 重量级锁:真正调用操作系统互斥量

六、final的内存语义

1. 特殊规则

  • 构造函数内:正确初始化的final字段,对其他线程立即可见
  • 禁止重排序:防止构造函数未完成就暴露对象引用

2. 安全发布示例

java 复制代码
class FinalExample {
    final int x;
    static FinalExample instance;
    
    public FinalExample() {
        x = 42; // final写
    }
    
    static void writer() {
        instance = new FinalExample(); // 安全发布
    }
    
    static void reader() {
        if (instance != null) {
            System.out.println(instance.x); // 保证看到x=42
        }
    }
}

七、JMM与硬件关系

Java概念 硬件对应
主内存 RAM内存
工作内存 CPU缓存/寄存器
内存屏障 CPU内存屏障指令
volatile lock指令+CACHE一致性协议

八、常见误区

1. volatile ≠ 原子性

java 复制代码
volatile int count = 0;
count++; // 仍然不是原子操作!

2. synchronized性能差?

  • 现代JVM已大幅优化(偏向锁/自适应自旋)
  • 竞争不激烈时开销很小

3. final只在编译期有效?

  • 运行期仍有内存语义保证

九、终极口诀

"JMM管线程内存,三大问题要记牢

可见有序加原子,volatile能解前两样

锁住同步最保险,happens-before是准绳

内存屏障底层撑,多线程安全有保障"

理解JMM,你就能写出线程安全的高性能代码! 🔒➡️🚀

相关推荐
小蜜蜂嗡嗡32 分钟前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi0038 分钟前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体
zhangphil2 小时前
Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值
android
你过来啊你2 小时前
Android View的绘制原理详解
android
移动开发者1号5 小时前
使用 Android App Bundle 极致压缩应用体积
android·kotlin
移动开发者1号5 小时前
构建高可用线上性能监控体系:从原理到实战
android·kotlin
ii_best10 小时前
按键精灵支持安卓14、15系统,兼容64位环境开发辅助工具
android
美狐美颜sdk10 小时前
跨平台直播美颜SDK集成实录:Android/iOS如何适配贴纸功能
android·人工智能·ios·架构·音视频·美颜sdk·第三方美颜sdk
恋猫de小郭15 小时前
Meta 宣布加入 Kotlin 基金会,将为 Kotlin 和 Android 生态提供全新支持
android·开发语言·ios·kotlin
aqi0016 小时前
FFmpeg开发笔记(七十七)Android的开源音视频剪辑框架RxFFmpeg
android·ffmpeg·音视频·流媒体