java线程安全需同时解决原子性、可见性、有序性:原子性防“读-改-写”插队,用synchronized、lock或原子类;可见性确保修改被及时感知,靠volatile、synchronized或final;有序性阻止指令重排,依赖volatile内存屏障或synchronized happens-before规则。

Java 线程安全的核心,就是把原子性、可见性、有序性这三个问题逐个堵住。它们不是孤立存在的,很多工具能同时解决多个问题,但理解各自的作用边界,才能用对、不滥用。
原子性:防止“读-改-写”被插队
像 i++ 这种操作,表面一行,实际分三步:读 i 值 → 加 1 → 写回 i。多线程下极易发生“两个线程都读到 5,各自加 1 写回 6”,最终只加了一次。
- 用 synchronized 或 ReentrantLock 包裹临界区,让操作串行执行
- 用 AtomicInteger、AtomicLong 等原子类,底层靠 CAS 指令保证单个变量的读写+更新是原子的
- 避免依赖 long/double 的非 volatile 读写(JDK8 前可能“撕裂”),如需原子,加 volatile 或用 AtomicLong
可见性:确保“改了就能被看见”
线程修改变量后,值可能还卡在 CPU 缓存里没刷到主内存,其他线程一直读旧值——比如 while(!flag) 死循环停不下来。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- volatile 是最轻量级方案:写操作强制刷新到主内存,读操作强制从主内存加载
- synchronized 和 Lock 在解锁前会把工作内存中所有共享变量刷新回主内存,加锁时也会从主内存重新读取
- final 字段在构造器内完成初始化后,对其他线程天然可见(JMM 保证)
有序性:阻止指令重排序“乱套”
CPU 和编译器为优化性能,可能调整语句执行顺序。单线程不影响结果,但多线程下可能出大问题——比如双重检查单例中 new Singleton() 被重排为“分配内存→赋引用→初始化”,导致其他线程拿到未初始化的对象。
- volatile 不仅保可见,还禁止其修饰变量前后的指令重排序(插入内存屏障)
- synchronized 块内代码天然遵循 happens-before 规则,不会与块外指令重排
- 显式使用 java.util.concurrent.locks.LockSupport 或 Unsafe 插入内存屏障(高级场景,慎用)
真正写并发代码时,别指望一个关键字包打天下。volatile 不能替代 synchronized 解决原子性;synchronized 开销大,高频计数优先选 LongAdder;而不可变对象和 ThreadLocal 则是从源头减少共享,比补救更高效。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










