目录

一、核心基础:什么是 CAS?

1. CAS 定义

2. CAS 工作原理

3. CAS 的优缺点

4. CAS 的应用

二、核心锁:synchronized 全阶段优化

1. 锁优化的核心目标

2. synchronized 锁升级全流程

(1)无锁状态

(2)偏向锁(第一个线程获取锁)

(3)轻量级锁(多个线程交替竞争)

(4)重量级锁(多线程激烈竞争)

3. synchronized 其他优化手段

4. 锁升级总结

三、Java 主流锁策略分类总结

1. 乐观锁 vs 悲观锁

2. 公平锁 vs 非公平锁

3. 可重入锁 vs 不可重入锁

4. 共享锁 vs 排他锁

5. 分段锁

6. 自旋锁

四、CAS 与 synchronized 核心对比

五、使用场景总结

总结


在 Java 高并发编程中,是解决线程安全问题的核心手段,从早期简单粗暴的synchronized,到无锁化的 CAS 算法,再到 JDK 对锁的层层优化,最终形成了一套完整的锁策略体系。本文将系统化梳理CAS 原理synchronized 锁优化全流程以及Java 主流锁策略,帮你彻底吃透 Java 锁机制。

一、核心基础:什么是 CAS?

1. CAS 定义

CAS(Compare And Swap,比较并交换)是一种无锁乐观并发算法,无需加锁即可实现线程安全的原子操作,是 Java 并发包(java.util.concurrent)的核心基石。

2. CAS 工作原理

CAS 包含三个核心参数:

  • V:内存中要修改的变量值(主内存值)
  • A:线程读取到的旧预期值
  • B:线程准备写入的新值

执行流程

  1. 线程先读取变量值作为预期值 A
  2. 执行计算,得到新值 B
  3. 原子性执行比较:若内存中的V == A(说明期间无其他线程修改),则将V更新为B
  4. V != A(说明期间被其他线程修改),则操作失败,线程可重试(自旋)。

整个过程是硬件级别的原子操作,不涉及线程阻塞,效率远高于重量级锁。

3. CAS 的优缺点

  • 优点:无锁、无线程阻塞 / 唤醒开销,高并发下性能优于悲观锁;
  • 缺点
    1. ABA 问题:变量从 A→B→A,CAS 无法感知变化(解决方案:加版本号 / 时间戳,如AtomicStampedReference);
    2. 长时间自旋开销:并发冲突高时,线程反复重试会占用 CPU;
    3. 仅支持单个变量的原子操作,无法保证代码块的原子性。

4. CAS 的应用

Java 中的原子类(AtomicIntegerAtomicBoolean)、ConcurrentHashMap、线程池等核心组件,底层均基于 CAS 实现。


二、核心锁:synchronized 全阶段优化

synchronized是 Java 原生的悲观互斥锁,早期是重量级锁(性能极低),JDK1.6 后 JVM 对其进行了全方位优化,形成了无锁→偏向锁→轻量级锁→重量级锁的链式升级流程(锁只能升级,不能降级)。

1. 锁优化的核心目标

减少用户态与内核态的切换(线程阻塞 / 唤醒依赖操作系统,开销极大),尽可能在用户态完成线程同步。

2. synchronized 锁升级全流程

(1)无锁状态
  • 场景:没有线程竞争锁对象;
  • 原理:对象头无任何锁标记,线程直接执行代码。
(2)偏向锁(第一个线程获取锁)
  • 场景:只有一个线程反复获取锁,无竞争;
  • 原理:JVM 会在对象头中记录持有锁的线程 ID,该线程后续再次获取锁时,无需任何同步操作,直接放行;
  • 优势:消除无竞争场景下的锁开销,是最轻量的锁。
(3)轻量级锁(多个线程交替竞争)
  • 场景:多个线程交替获取锁,无长时间阻塞;
  • 原理:偏向锁遇到竞争时,立即升级为轻量级锁,线程通过CAS 自旋尝试获取锁,不阻塞线程;
  • 优势:避免线程阻塞,适合短时间、低冲突的并发场景。
(4)重量级锁(多线程激烈竞争)
  • 场景:多个线程同时争抢锁,自旋多次失败;
  • 原理:轻量级锁升级为重量级锁,线程获取锁失败会进入阻塞队列,由操作系统调度;
  • 特点:线程阻塞,无 CPU 空转开销,但切换成本最高。

3. synchronized 其他优化手段

  1. 锁消除:JVM 通过逃逸分析,判断锁对象仅被单线程使用,自动删除无用锁;
  2. 锁粗化:JVM 将多次连续的加锁 / 解锁操作,合并为一次加锁,减少开销;
  3. 自旋锁:线程获取锁失败时,不立即阻塞,循环重试(配合轻量级锁使用)。

4. 锁升级总结

锁状态适用场景核心原理性能
偏向锁单线程无竞争记录线程 ID,无同步操作最高
轻量级锁线程交替竞争CAS 自旋,用户态执行
重量级锁多线程激烈竞争操作系统阻塞线程

三、Java 主流锁策略分类总结

除了synchronized的锁升级,Java 还根据不同维度划分了多种锁策略:

1. 乐观锁 vs 悲观锁

  • 悲观锁:默认线程会发生竞争,先加锁再操作,线程阻塞(如synchronizedReentrantLock);
  • 乐观锁:默认无竞争,先操作再验证,无锁(如 CAS 算法)。

2. 公平锁 vs 非公平锁

  • 公平锁:线程按申请顺序获取锁,无饥饿(如new ReentrantLock(true));
  • 非公平锁:线程可 “插队” 获取锁,吞吐量更高(如synchronized、默认ReentrantLock)。

3. 可重入锁 vs 不可重入锁

  • 可重入锁:同一线程可重复获取自己持有的锁,避免死锁(synchronizedReentrantLock);
  • 不可重入锁:线程重复获取锁会阻塞,易死锁。

4. 共享锁 vs 排他锁

  • 排他锁(写锁):同一时间只允许一个线程持有(synchronizedReentrantLock);
  • 共享锁(读锁):多个线程可同时持有,仅允许读操作(如ReentrantReadWriteLock的读锁)。

5. 分段锁

  • 原理:将数据分段,每段加独立锁,减少锁竞争;
  • 应用:JDK1.7 的ConcurrentHashMap,大幅提升并发读写效率。

6. 自旋锁

  • 原理:线程获取锁失败时,循环重试而非阻塞,减少线程切换开销;
  • 缺点:高并发下占用 CPU,适合短任务场景。

四、CAS 与 synchronized 核心对比

表格

特性CASsynchronized
锁类型乐观锁、无锁悲观锁、有锁
原子性单个变量原子操作代码块 / 方法原子操作
线程状态无阻塞,自旋竞争时阻塞
性能低冲突:极高;高冲突:一般低冲突:低;高冲突:稳定
适用场景原子变量、短时间操作代码块、复杂业务逻辑
核心问题ABA、自旋开销锁竞争、线程阻塞

五、使用场景总结

  1. 简单原子变量操作:优先用CAS + 原子类(无锁高性能);
  2. 低并发、代码简洁优先:使用synchronized(JVM 自动优化,无需手动管理);
  3. 高并发、灵活控制锁:使用ReentrantLock(可公平、可超时、可中断);
  4. 读多写少场景:使用读写锁ReentrantReadWriteLock);
  5. 高并发集合:使用ConcurrentHashMap(CAS + 分段锁 / 红黑树)。

总结

  1. CAS 是无锁乐观算法,靠比较并交换实现原子操作,是 Java 并发的底层核心;
  2. synchronized 经过 JDK 优化,形成无锁→偏向锁→轻量级锁→重量级锁的升级流程,大幅提升性能;
  3. Java 锁策略围绕乐观 / 悲观、公平 / 非公平、共享 / 排他等维度划分,需根据场景选择最优方案;
  4. 实际开发中,优先用无锁 CAS,其次用优化后的 synchronized,复杂场景用显式锁,兼顾性能与线程安全。

更多推荐