并发编程的本质-解决三性问题

并发编程的本质:通过合理的机制(锁、原子类、内存屏障等)协调多线程对共享资源的访问,确保三性不被破坏。

所以实际上JMM只是Java为了解决并发问题引入的一种模型(规范),提供的一种结构化的解决方案。

JMM是共享内存模型,提供了三性问题的解决办法

一、并发三性的定义与重要性

特性 定义 问题场景 解决方案示例
原子性 一个操作是不可分割的,要么全部执行成功,要么完全不执行。 多线程同时修改共享变量(如 i++),导致结果不一致。 synchronizedLock、原子类(AtomicInteger
可见性 一个线程修改共享变量后,其他线程能立即看到修改后的值。 线程 A 修改了变量,但线程 B 仍读到旧值(如循环检测标志位时死循环)。 volatilesynchronizedLock
有序性 程序执行的顺序符合代码的先后逻辑,避免编译器和 CPU 的指令重排序导致意外结果。 线程 A 先执行写操作 a=1,再写 flag=true,但线程 B 可能先看到 flag=true,后看到 a=0 volatilesynchronizedfinalhappens-before 规则

二、三性之间的关系

  1. 原子性是基础
    若操作不具备原子性(如非原子类的 i++),多线程并发时必然导致数据不一致。
  2. 可见性依赖原子性
    即使操作是原子的,若修改不可见(如未用 volatile),其他线程仍可能读取旧值。
  3. 有序性影响可见性
    指令重排序可能导致共享变量的修改顺序对其他线程不可见(如双重检查锁单例模式需用 volatile)。

三、如何保证并发三性

1. 原子性的保证

  • 锁机制synchronizedReentrantLock等。
  • 无锁编程 :原子类(AtomicInteger)、LongAdderCAS
  • 不可变对象final 修饰的不可变对象天然线程安全。

2. 可见性的保证

  • volatile 关键字:强制读写直接操作主内存。
  • 锁机制:锁的释放会强制同步工作内存到主内存,锁的获取会强制从主内存加载。
  • final 关键字 :正确构造的 final 字段对其他线程可见。

3. 有序性的保证

  • volatile 关键字:禁止指令重排序(插入内存屏障)。
  • synchronized/Lock:同步块内的代码不会被重排序到块外。
  • happens-before 规则:JMM 定义的顺序性约束(如线程启动规则、传递性规则等)。

四、实际场景分析

1. 单例模式(双重检查锁)

java 复制代码
public class Singleton {
    private static volatile Singleton instance; // 必须用 volatile 保证有序性

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton(); // 可能出现指令重排序
                }
            }
        }
        return instance;
    }
}
  • 问题 :若不用 volatilenew Singleton() 的指令可能重排序(先分配内存地址,再初始化对象),导致其他线程拿到未初始化的对象。
  • 解决volatile 禁止重排序,保证有序性。

2. 高并发计数器

java 复制代码
public class Counter {
    private LongAdder count = new LongAdder(); // 高并发下性能优于 AtomicLong

    public void increment() {
        count.increment(); // 原子性 + 可见性
    }

    public long get() {
        return count.sum();
    }
}
  • 原理LongAdder 通过分段 CAS 减少竞争,保证原子性和可见性。

五、总结

维度 核心问题 解决手段 工具/关键字
原子性 操作不可分割 锁、原子类、CAS synchronizedAtomicIntegerLongAdder
可见性 修改后立即可见 强制主内存同步 volatilesynchronizedLock
有序性 指令按预期顺序执行 禁止重排序、happens-before 规则 volatilefinalsynchronized
相关推荐
雪隐23 分钟前
个人电脑玩AI-16让5060 Ti给你打工——5060Ti 16G 跑 MiniMax-Music-3:从下载到 60s 出歌的全流程
前端·人工智能·后端
报错小能手1 小时前
Go 语言结构 基础语法
开发语言·后端·golang
暗黑小白1 小时前
参数从哪来、何时来 —— 提取时机与平台化 Slot 管理
人工智能·后端·大模型·ai agent
剩下了什么1 小时前
go语言 Ctx:「错误三:在 Context 中存储可变值」
开发语言·后端·golang
程序员鱼皮2 小时前
DeepSeek Harness 最新邪修曝光!被吹成核弹的极简模式,真的夯吗?
前端·后端·ai编程
Gopher_HBo2 小时前
请求绑定与校验
后端
长栎2 小时前
你写的撤销功能,99% 是伪 Memento——Undo 不是存个备份那么简单
后端
笨鸟飞不快2 小时前
RocketMQ Lite Topic 流程梳理与设计解读
后端·rocketmq
步行cgn2 小时前
MyBatis 查询结果字段为 null?一文讲透下划线命名与驼峰映射问题
后端
技术长镜头2 小时前
别再只会“加索引”:从磁盘页到 B+Tree,彻底理解 MySQL 索引的设计与运行
后端·mysql