并发编程:Java 如何解决 可见性,有序性和原子性

在 Java 并发编程中,可见性、有序性、原子性是并发错误的三大核心根源。


✅ 一、如何解决 可见性问题

🧠 问题回顾:

  • 一个线程修改了共享变量,其他线程看不到(缓存没有刷新)。

🔧 Java 解决方式:

机制说明
volatile禁止线程缓存变量,修改立即写入主内存;读取强制从主内存读。 ✅轻量方式
synchronized加锁会刷新工作内存,进入同步块前读取主内存,退出时写回主内存
final构造函数安全发布(对象构造完成前不能被其他线程看到)
JMM 的 happens-before 规则Java 的内存模型定义了一系列可见性保证规则

✅ 二、如何解决 有序性问题

🧠 问题回顾:

  • JVM 和 CPU 会重排序指令,导致多线程执行顺序不一致。

🔧 Java 解决方式:

机制说明
volatile禁止重排序(对读写操作的指令不会和前后的指令重排序)
synchronized锁具备内存屏障效果,进入和退出同步块都包含“顺序约束”
happens-before 语义JMM 规定了某些操作之间的“先发生于”关系,编译器/CPU 会保持顺序

📝 举例(重排序引发的问题):

int a = 0;
boolean flag = false;

Thread A:
    a = 1;
    flag = true; // 可能重排序到前面

Thread B:
    if (flag) {
        System.out.println(a); // 可能输出 0
    }

使用 volatile flag 可禁止重排序。


✅ 三、如何解决 原子性问题

🧠 问题回顾:

  • 多线程并发修改变量时,中间过程被打断,导致结果错误。

🔧 Java 解决方式:

机制说明
synchronized让某段代码在任意时刻只允许一个线程执行,从而保证操作的原子性
ReentrantLock可替代 synchronized,有更强的功能(可中断、公平锁、tryLock)
AtomicInteger 等原子类JDK 提供的原子操作类,底层基于 CAS,可高性能地支持线程安全的加减等操作
数据结构并发容器(如 ConcurrentHashMap内部采用分段锁或CAS原语,支持高性能并发访问

✅ 总结

并发问题典型现象Java 解决机制
可见性线程 A 修改变量,线程 B 看不到volatilesynchronizedfinal、JMM happens-before
有序性指令被重排序,行为反直觉volatilesynchronized、JMM 顺序规则
原子性多线程修改共享变量,结果错误synchronizedLockAtomicXXX、并发容器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值