JMM怎么保证线程安全的(可见性,原子性,有序性)?

1 个回答

  • 随风起舞
    天越来越黑,星星会越来越亮。
    JMM 保证线程安全,主要是通过**可见性、原子性、有序性**这三大特性来实现的,每个特性背后都有对应的实现机制。 ## 1. 可见性(Visibility) **含义**:一个线程对共享变量的修改,能被其他线程立即看到。 **JMM 实现方式**: * **`volatile`** * 写变量时,强制将工作内存中的值刷新到主内存 * 读变量时,强制从主内存重新读取 * **`synchronized` / `Lock`** * 释放锁时,强制将工作内存修改同步到主内存 * 获取锁时,强制清空工作内存,从主内存加载最新值 * **内存屏障(Memory Barrier)** * JMM 在生成指令时插入屏障,保证刷新顺序和可见性 ## 2. 原子性(Atomicity) **含义**:操作不可被中断,要么全部执行成功,要么全部失败。 **JMM 实现方式**: * 对于**基本类型的读/写**(long/double 可能例外),JMM 保证原子性 * **`synchronized` / `Lock`**:通过互斥锁保证临界区代码的原子性 * **CAS(Compare And Swap)**:配合 `AtomicInteger` 等原子类,在无锁情况下也能实现原子操作 ## 3. 有序性(Ordering) **含义**:程序执行的顺序对其他线程可见的效果与代码顺序一致(禁止影响结果的指令重排)。 **JMM 实现方式**: * **`volatile`**:写操作后插入 **StoreStore/StoreLoad 屏障**,读操作前插入 **LoadLoad/LoadStore 屏障** * **`synchronized` / `Lock`**:锁的释放和获取之间会隐含内存屏障,阻止重排 * **Happens-Before 规则**(JMM 核心原则): 1. 程序次序规则(同一线程内按代码顺序执行) 2. 锁定规则(解锁先于后续的加锁) 3. volatile 规则(对 volatile 变量的写先于读) 4. 线程启动/终止规则(`start()` 在 `run()` 之前,`run()` 在 `join()` 之前) ## 总结对照表 | 特性 | 关键机制 | 关键工具 | | ------- | ------------------- | ------------------ | | **可见性** | 主内存与工作内存同步、内存屏障 | `volatile`、锁 | | **原子性** | 互斥访问、CAS | `synchronized`、CAS | | **有序性** | 禁止重排、Happens-Before | `volatile`、锁、屏障 |
    发布于 2025-08-13 10:05 •IP属地 湖北
    举报
    评论
    收藏