目录
- Java锁体系概览
- synchronized 内置锁
- ReentrantLock 可重入锁
- ReentrantReadWriteLock 读写锁
- StampedLock 邮戳锁
- Semaphore 信号量
- CountDownLatch 闭锁
- CyclicBarrier 循环屏障
- Phaser 阶段器
- LockSupport 锁支持
- 原子类(Atomic Classes)
- 锁的性能对比
- 最佳实践与选择指南
一、Java锁体系概览
1.1 Java锁分类
Java锁体系:
┌─────────────────────────────────────────────────────┐
│ 按锁的性质分类 │
├──────────────────────────────────────────────────────┤
│ │
│ 1. 悲观锁 vs 乐观锁 │
│ - 悲观锁: synchronized, ReentrantLock │
│ - 乐观锁: CAS操作, 原子类 │
│ │
│ 2. 独占锁 vs 共享锁 │
│ - 独占锁: synchronized, ReentrantLock │
│ - 共享锁: ReentrantReadWriteLock.ReadLock │
│ │
│ 3. 公平锁 vs 非公平锁 │
│ - 公平锁: ReentrantLock(true) │
│ - 非公平锁: synchronized, ReentrantLock(false) │
│ │
│ 4. 可重入锁 vs 不可重入锁 │
│ - 可重入锁: synchronized, ReentrantLock │
│ - 不可重入锁: 自定义实现 │
│ │
│ 5. 互斥锁 vs 读写锁 │
│ - 互斥锁: synchronized, ReentrantLock │
│ - 读写锁: ReentrantReadWriteLock │
└─────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────┐
│ 按实现方式分类 │
├─────────────────────────────────────────────────────┤
│ │
│ 1. 内置锁(JVM实现) │
│ - synchronized │
│ │
│ 2. 显式锁(JDK实现) │
│ - ReentrantLock │
│ - ReentrantReadWriteLock │
│ - StampedLock │
│ │
│ 3. 同步工具类 │
│ - Semaphore │
│ - CountDownLatch │
│ - CyclicBarrier │
│ - Phaser │
│ │
│ 4. 原子类(CAS实现) │
│ - AtomicInteger │
│ - AtomicLong │
│ - AtomicReference │
│ - AtomicStampedReference │
└─────────────────────────────────────────────────────┘
1.2 Java锁对比表
| 锁类型 | 性质 | 公平性 | 可重入 | 性能 | 适用场景 |
|---|---|---|---|---|---|
| synchronized | 独占、悲观 | 非公平 | ✅ | 高 | 通用场景 |
| ReentrantLock | 独占、悲观 | 可选 | ✅ | 中 | 需要高级特性 |
| ReentrantReadWriteLock | 读写分离 | 可选 | ✅ | 中 | 读多写少 |
| StampedLock | 读写分离 | 非公平 | ❌ | 高 | 读多写少(JDK8+) |
| Semaphore | 共享、计数 | 可选 | ❌ | 中 | 限流、资源控制 |
| CountDownLatch | 一次性 | N/A | N/A | 高 | 等待多个任务完成 |
| CyclicBarrier | 可重用 | N/A | N/A | 中 | 多线程同步点 |
| Phaser | 分阶段 | N/A | N/A | 中 | 复杂同步场景 |
| AtomicInteger | 乐观锁 | N/A | N/A | 极高 | 计数器、状态标志 |
二、synchronized 内置锁
2.1 synchronized 基本用法
/**
* synchronized 三种使用方式
*/
public class SynchronizedUsage {
private int count = 0;
private static int staticCount = 0;
private final Object lock = new Object();
/**
* 方式1: 修饰实例方法
*/
public synchronized void instanceMethod() {
count++;
// 锁对象是当前实例(this)。可以简单理解为:谁调用方法,谁就是锁对象 。
}
/**
* 方式2: 修饰静态方法
*/
public static synchronized void staticMethod() {
staticCount++;
// 锁对象是类对象(SynchronizedUsage.class)
}
/**
* 方式3: 修饰代码块
*/
public void blockMethod() {
synchronized (lock) {
count++;
// 锁对象是指定的lock对象
}
}
}
2.2 synchronized 底层原理
2.2.1 字节码层面
工作原理
- MONITORENTER :尝试获取锁,如果成功则继续执行,否则阻塞当前线程
- 正常路径 MONITOREXIT :代码正常执行完成后释放锁
- 异常路径 MONITOREXIT :即使发生异常,也能确保锁被释放,避免死锁
/**
* synchronized 字节码分析
*/
public class SynchronizedBytecode {
public void synchronizedMethod() {
synchronized (this) {
// 业务逻辑
}
}
}
// 编译后的字节码(简化版):
/*
public synchronizedMethod()V
ALOAD 0 // 加载this到操作数栈
DUP // 复制this引用
ASTORE 1 // 存储到局部变量1(保存锁对象引用)
MONITORENTER // 进入监视器(获取锁)
TRY_BLOCK_1: // 开始try块
// 业务逻辑代码
GOTO END_BLOCK_1 // 跳过异常处理代码
CATCH_BLOCK_1: // 捕获异常的代码块
ALOAD 1 // 加载局部变量1(this引用)
MONITOREXIT // 异常路径上的MONITOREXIT
ATHROW // 重新抛出异常
END_BLOCK_1: // 正常执行结束
ALOAD 1 // 加载局部变量1(this引用)
MONITOREXIT // 正常路径上的MONITOREXIT
RETURN // 方法返回
*/
2.2.2 对象头与Mark Word
Java对象内存布局:
┌─────────────────────────────────────────────────────────────┐
│ 对象头(Object Header) │
├─────────────────────────────────────────────────────────────┤
│ Mark Word (64位): │
│ [25位未使用][31位哈希码][1位未使用][4位年龄][1位偏向][2位锁标志]│
│ │
│ 锁标志位含义: │
│ 00: 轻量级锁(Lightweight Lock) │
│ 01: 无锁/偏向锁(Normal/Biased) │
│ 10: 重量级锁(Heavyweight Lock) │
│ 11: GC标记(Marked for GC) │
│ │
│ Class Metadata Pointer (64位): │
│ - 指向类的元数据(Klass) │
│ │
│ Array Length (可选,仅数组): │
│ - 数组长度 │
└────────────────────────────────────────────────────────────┘
2.2.3 锁升级过程详解
synchronized锁升级完整流程:
无锁状态(Normal)
│
│ 第一个线程访问
▼
偏向锁(Biased Lock)
│
│ 第二个线程竞争
▼
轻量级锁(Lightweight Lock)
│
│ 自旋失败或竞争激烈
▼
重量级锁(Heavyweight Lock)
详细过程:
阶段1: 偏向锁
- 第一个线程访问时,JVM使用CAS将线程ID写入Mark Word
- 后续同一线程访问时,无需CAS,直接进入
- 性能最优(几乎无开销)
阶段2: 轻量级锁
- 第二个线程竞争时,撤销偏向锁
- 在栈帧中创建锁记录(Lock Record)
- 使用CAS将Mark Word指向锁记录
- 如果CAS成功 → 获取轻量级锁
- 如果CAS失败 → 自旋等待或升级
阶段3: 重量级锁
- 自旋失败(超过阈值)或竞争激烈
- 创建Monitor对象
- Mark Word指向Monitor对象
- 线程进入阻塞队列(EntryList)
- 操作系统级别的阻塞(Mutex)
2.3 Monitor对象深入解析
/**
* Monitor对象结构(概念模型)
*
* 注意:实际实现是C++代码(ObjectMonitor)
*/
public class ObjectMonitor {
/**
* 持有锁的线程
*/
private Thread owner;
/**
* 重入次数
*/
private int recursions;
/**
* 等待队列(调用wait()的线程)
*/
private WaitSet waitSet;
/**
* 阻塞队列(竞争锁的线程)
*/
private EntryList entryList;
/**
* 获取锁
*/
public void enter() {
Thread currentThread = Thread.currentThread();
// 1. 尝试快速获取锁(CAS)
if (compareAndSetOwner(null, currentThread)) {
recursions = 1;
return;
}
// 2. 重入检查
if (owner == currentThread) {
recursions++;
return;
}
// 3. 获取锁失败,进入阻塞队列
entryList.add(currentThread);
// 4. 操作系统级别的阻塞(park)
park(currentThread);
}
/**
* 释放锁
*/
public void exit() {
Thread currentThread = Thread.currentThread();
if (owner != currentThread) {
throw new IllegalMonitorStateException();
}
if (--recursions > 0) {
return; // 还有重入,不释放
}
owner = null;
// 唤醒阻塞队列中的线程
Thread nextThread = entryList.remove();
if (nextThread != null) {
unpark(nextThread);
}
}
/**
* 等待(释放锁,进入等待队列)
*/
public void wait() {
Thread currentThread = Thread.currentThread();
if (owner != currentThread) {
throw new IllegalMonitorStateException();
}
int savedRecursions = recursions;
owner = null;
recursions = 0;
// 进入等待队列
waitSet.add(currentThread);
// 唤醒阻塞队列中的线程
Thread nextThread = entryList.remove();
if (nextThread != null) {
unpark(nextThread);
}
// 阻塞当前线程
park(currentThread);
// 被唤醒后,重新获取锁
enter();
recursions = savedRecursions;
}
/**
* 通知(唤醒等待队列中的线程)
*/
public void notify() {
Thread currentThread = Thread.currentThread();
if (owner != currentThread) {
throw new IllegalMonitorStateException();
}
Thread waitingThread = waitSet.remove();
if (waitingThread != null) {
entryList.add(waitingThread);
}
}
}
2.4 synchronized 性能优化
synchronized性能优化机制:
1. 偏向锁(Biased Locking)
- 目的: 优化无竞争场景
- 原理: 第一个线程访问时,将线程ID写入Mark Word
- 优势: 同一线程再次访问时无需CAS操作
- 劣势: 有竞争时需要撤销,开销较大
2. 轻量级锁(Lightweight Locking)
- 目的: 优化低竞争场景
- 原理: 使用CAS和栈帧中的锁记录
- 优势: 线程不会阻塞(自旋等待)
- 劣势: 自旋消耗CPU
3. 自适应自旋(Adaptive Spinning)
- 目的: 优化自旋次数
- 原理: 根据历史成功率动态调整自旋次数
- 优势: 平衡CPU消耗和响应时间
4. 锁粗化(Lock Coarsening)
- 目的: 减少锁的获取和释放次数
- 原理: 将连续的synchronized块合并
- 优势: 减少开销
5. 锁消除(Lock Elimination)
- 目的: 消除不必要的锁
- 原理: 逃逸分析证明对象不会逃逸
- 优势: 完全消除锁开销
三、ReentrantLock 可重入锁
3.1 ReentrantLock 基本用法
/**
* ReentrantLock 基本用法
*/
public class ReentrantLockUsage {
private final ReentrantLock lock = new ReentrantLock();
/**
* 基本用法
*/
public void basicUsage() {
lock.lock();
try {
// 业务逻辑
} finally {
lock.unlock();
}
}
/**
* 尝试获取锁(非阻塞)
*/
public void tryLockUsage() {
if (lock.tryLock()) {
try {
// 业务逻辑
} finally {
lock.unlock();
}
} else {
// 获取锁失败的处理
}
}
/**
* 带超时的获取锁
*/
public void tryLockWithTimeout() throws InterruptedException {
if (lock.tryLock(5, TimeUnit.SECONDS)) {
try {
// 业务逻辑
} finally {
lock.unlock();
}
} else {
// 超时未获取到锁
}
}
/**
* 可中断的获取锁
*/
public void interruptibleLock() throws InterruptedException {
lock.lockInterruptibly();
try {
// 业务逻辑
} finally {
lock.unlock();
}
}
}
3.2 ReentrantLock 核心特性
ReentrantLock 核心特性:
1. 可重入性
- 同一线程可以多次获取同一把锁
- 内部维护重入次数计数器
- 释放锁时需要释放相同次数
2. 公平性
- 公平锁: 按照请求顺序获取锁(FIFO)
- 非公平锁: 允许插队(性能更好)
- 默认: 非公平锁
3. 可中断性
- lockInterruptibly()支持中断
- 等待锁时可以被中断
4. 条件变量
- 支持多个Condition
- 可以实现更复杂的同步场景
3.3 AQS(AbstractQueuedSynchronizer)原理
3.3.1 AQS核心设计
AQS核心设计思想:
┌─────────────────────────────────────────────────────────┐
│ AQS设计模式 │
├─────────────────────────────────────────────────────────┤
│ │
│ 模板方法模式: │
│ - acquire(): 模板方法(固定流程) │
│ - tryAcquire(): 钩子方法(由子类实现) │
│ │
│ 核心组件: │
│ - state: 同步状态(volatile int) │
│ - head: 同步队列头节点 │
│ - tail: 同步队列尾节点 │
│ - Node: 等待队列节点 │
│ │
│ 同步队列(CLH队列变种): │
│ - 双向链表结构 │
│ - 每个节点代表一个等待的线程 │
│ - 支持公平锁和非公平锁 │
└─────────────────────────────────────────────────────────┘
3.3.2 AQS同步队列结构
/**
* AQS同步队列节点结构
*/
static final class Node {
/**
* 节点模式
*/
static final Node SHARED = new Node(); // 共享模式
static final Node EXCLUSIVE = null; // 独占模式
/**
* 等待状态
*/
volatile int waitStatus;
static final int CANCELLED = 1; // 已取消
static final int SIGNAL = -1; // 需要唤醒后继节点
static final int CONDITION = -2; // 在条件队列中
static final int PROPAGATE = -3; // 共享模式传播
/**
* 前驱节点
*/
volatile Node prev;
/**
* 后继节点
*/
volatile Node next;
/**
* 等待的线程
*/
volatile Thread thread;
/**
* 条件队列中的下一个节点
*/
Node nextWaiter;
}
3.3.3 AQS获取锁完整流程
/**
* AQS获取锁完整流程(源码级别)
*/
public abstract class AbstractQueuedSynchronizer {
/**
* 获取独占锁(模板方法)
*/
public final void acquire(int arg) {
// 1. 尝试获取锁
if (!tryAcquire(arg) &&
// 2. 获取失败,加入队列并自旋
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) {
// 3. 如果被中断,恢复中断状态
selfInterrupt();
}
}
/**
* 尝试获取锁(由子类实现)
*/
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
/**
* 加入同步队列
*/
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
if (pred != null) {
node.prev = pred;
// CAS设置尾节点
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
// CAS失败,使用enq方法(自旋重试)
enq(node);
return node;
}
/**
* 在队列中自旋获取锁
*/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
// 如果前驱节点是头节点,尝试获取锁
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// 检查是否需要阻塞
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt()) {
interrupted = true;
}
}
} finally {
if (failed) {
cancelAcquire(node);
}
}
}
/**
* 检查是否需要阻塞
*/
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL) {
// 前驱节点需要唤醒后继节点,可以安全阻塞
return true;
}
if (ws > 0) {
// 前驱节点已取消,跳过
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
// 设置前驱节点为SIGNAL状态
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
/**
* 阻塞并检查中断
*/
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
}
3.4 ReentrantLock 公平锁 vs 非公平锁
/**
* ReentrantLock 公平锁与非公平锁实现对比
*/
public class ReentrantLockFairness {
/**
* 非公平锁实现
*/
static final class NonfairSync extends Sync {
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 非公平锁:直接尝试获取,不检查队列
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
} else if (current == getExclusiveOwnerThread()) {
// 重入
int nextc = c + acquires;
if (nextc < 0) {
throw new Error("Maximum lock count exceeded");
}
setState(nextc);
return true;
}
return false;
}
}
/**
* 公平锁实现
*/
static final class FairSync extends Sync {
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 公平锁:检查是否有前驱节点
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
} else if (current == getExclusiveOwnerThread()) {
// 重入
int nextc = c + acquires;
if (nextc < 0) {
throw new Error("Maximum lock count exceeded");
}
setState(nextc);
return true;
}
return false;
}
/**
* 检查是否有前驱节点
*/
public final boolean hasQueuedPredecessors() {
Node t = tail;
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
}
}
3.5 Condition 条件变量
/**
* Condition 条件变量使用
*/
public class ConditionUsage {
private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private boolean flag = false;
/**
* 等待条件
*/
public void awaitCondition() throws InterruptedException {
lock.lock();
try {
while (!flag) {
// 释放锁,进入等待队列
condition.await();
}
// 条件满足,执行业务逻辑
doSomething();
} finally {
lock.unlock();
}
}
/**
* 通知条件满足
*/
public void signalCondition() {
lock.lock();
try {
flag = true;
// 唤醒等待队列中的一个线程
condition.signal();
// 或者唤醒所有等待的线程
// condition.signalAll();
} finally {
lock.unlock();
}
}
/**
* 生产者-消费者示例
*/
public class ProducerConsumer {
private final ReentrantLock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
private final Queue<String> queue = new LinkedList<>();
private final int capacity = 10;
public void produce(String item) throws InterruptedException {
lock.lock();
try {
while (queue.size() == capacity) {
// 队列满,等待
notFull.await();
}
queue.offer(item);
// 通知消费者
notEmpty.signal();
} finally {
lock.unlock();
}
}
public String consume() throws InterruptedException {
lock.lock();
try {
while (queue.isEmpty()) {
// 队列空,等待
notEmpty.await();
}
String item = queue.poll();
// 通知生产者
notFull.signal();
return item;
} finally {
lock.unlock();
}
}
}
}
四、ReentrantReadWriteLock 读写锁
4.1 读写锁基本概念
读写锁原理:
┌───────────────────────────────────────────────┐
│ 读写锁特性 │
├───────────────────────────────────────────────┤
│ │
│ 读锁(共享锁): │
│ - 多个线程可以同时持有读锁 │
│ - 读锁与读锁不互斥 │
│ - 读锁与写锁互斥 │
│ │
│ 写锁(独占锁): │
│ - 同一时刻只有一个线程可以持有写锁 │
│ - 写锁与读锁互斥 │
│ - 写锁与写锁互斥 │
│ │
│ 锁降级: │
│ - 写锁可以降级为读锁 │
│ - 读锁不能升级为写锁 │
└───────────────────────────────────────────────┘
锁的兼容性矩阵:
| 读锁 | 写锁 | |
|---|---|---|
| 读锁 | ✅ | ❌ |
| 写锁 | ❌ | ❌ |
4.2 ReentrantReadWriteLock 实现原理
4.2.1 状态位设计
ReentrantReadWriteLock 状态位设计:
state (32位):
┌─────────────────────────────────────────┐
│ 高16位: 读锁持有数量 │
│ 低16位: 写锁重入次数 │
└─────────────────────────────────────────┘
示例:
state = 0x00010001
- 高16位: 0x0001 = 1(1个线程持有读锁)
- 低16位: 0x0001 = 1(写锁重入1次)
读锁获取:
- 检查写锁是否被持有(state低16位是否为0)
- 如果写锁未被持有,增加读锁计数(高16位+1)
写锁获取:
- 检查读锁和写锁是否都被持有(state是否为0)
- 如果都为0,设置写锁状态(低16位=1)
4.2.2 读写锁实现源码
/**
* ReentrantReadWriteLock 核心实现
*/
public class ReentrantReadWriteLock implements ReadWriteLock {
private final ReadLock readLock;
private final WriteLock writeLock;
private final Sync sync;
/**
* 同步器(继承AQS)
*/
abstract static class Sync extends AbstractQueuedSynchronizer {
// 读锁和写锁共享同一个state
// 高16位:读锁计数
// 低16位:写锁重入次数
static final int SHARED_SHIFT = 16;
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
/**
* 获取读锁数量
*/
static int sharedCount(int c) {
return c >>> SHARED_SHIFT;
}
/**
* 获取写锁重入次数
*/
static int exclusiveCount(int c) {
return c & EXCLUSIVE_MASK;
}
/**
* 读锁获取
*/
protected final int tryAcquireShared(int unused) {
Thread current = Thread.currentThread();
int c = getState();
// 如果写锁被持有,且不是当前线程持有,获取失败
if (exclusiveCount(c) != 0 &&
getExclusiveOwnerThread() != current) {
return -1;
}
int r = sharedCount(c);
if (!readerShouldBlock() &&
r < MAX_COUNT &&
compareAndSetState(c, c + SHARED_UNIT)) {
// 获取读锁成功
return 1;
}
return fullTryAcquireShared(current);
}
/**
* 写锁获取
*/
protected final boolean tryAcquire(int acquires) {
Thread current = Thread.currentThread();
int c = getState();
int w = exclusiveCount(c);
if (c != 0) {
// 如果读锁被持有,或者写锁被其他线程持有
if (w == 0 || current != getExclusiveOwnerThread()) {
return false;
}
// 写锁重入
if (w + acquires > EXCLUSIVE_MASK) {
throw new Error("Maximum lock count exceeded");
}
setState(c + acquires);
return true;
}
// 尝试获取写锁
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires)) {
return false;
}
setExclusiveOwnerThread(current);
return true;
}
}
}
4.3 读写锁使用示例
/**
* 读写锁实际应用示例
*/
@Service
@Slf4j
public class ReadWriteLockExample {
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private final ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
private final ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();
private Map<String, String> cache = new HashMap<>();
/**
* 读操作(多个线程可以并发读取)
*/
public String get(String key) {
readLock.lock();
try {
return cache.get(key);
} finally {
readLock.unlock();
}
}
/**
* 写操作(独占访问)
*/
public void put(String key, String value) {
writeLock.lock();
try {
cache.put(key, value);
} finally {
writeLock.unlock();
}
}
/**
* 锁降级示例
*/
public void lockDowngrade(String key, String value) {
writeLock.lock();
try {
// 写操作
cache.put(key, value);
// 锁降级:写锁降级为读锁
readLock.lock();
} finally {
writeLock.unlock(); // 释放写锁
}
try {
// 读操作(仍然持有读锁)
String result = cache.get(key);
// 处理结果...
} finally {
readLock.unlock();
}
}
}
五、StampedLock 邮戳锁
5.1 StampedLock 简介
StampedLock 特性(JDK 8+):
┌────────────────────────────────────────────────────────┐
│ StampedLock 特点 │
├────────────────────────────────────────────────────────┤
│ │
│ 1. 三种模式: │
│ - 写锁(Write Lock): 独占锁 │
│ - 悲观读锁(Pessimistic Read Lock): 类似读锁 │
│ - 乐观读(Optimistic Read): 无锁读取 │
│ │
│ 2. 性能优势: │
│ - 乐观读性能极高(无锁) │
│ - 适合读多写少场景 │
│ │
│ 3. 限制: │
│ - 不可重入 │
│ - 不支持条件变量(Condition) │
│ - 不支持公平锁 │
└───────────────────────────────────────────────────────┘
5.2 StampedLock 实现原理
/**
* StampedLock 使用示例
*/
public class StampedLockUsage {
private final StampedLock stampedLock = new StampedLock();
private double x, y;
/**
* 写锁
*/
public void write(double newX, double newY) {
long stamp = stampedLock.writeLock();
try {
x = newX;
y = newY;
} finally {
stampedLock.unlockWrite(stamp);
}
}
/**
* 悲观读锁
*/
public double read() {
long stamp = stampedLock.readLock();
try {
return Math.sqrt(x * x + y * y);
} finally {
stampedLock.unlockRead(stamp);
}
}
/**
* 乐观读(推荐)
*/
public double optimisticRead() {
// 1. 尝试乐观读(不获取锁)
long stamp = stampedLock.tryOptimisticRead();
double currentX = x;
double currentY = y;
// 2. 验证stamp是否有效(检查是否有写操作)
if (!stampedLock.validate(stamp)) {
// 3. 乐观读失败,升级为悲观读锁
stamp = stampedLock.readLock();
try {
currentX = x;
currentY = y;
} finally {
stampedLock.unlockRead(stamp);
}
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}
/**
* 锁升级(读锁升级为写锁)
*/
public void upgradeReadToWrite() {
long stamp = stampedLock.readLock();
try {
// 读操作
double currentX = x;
// 尝试升级为写锁
long writeStamp = stampedLock.tryConvertToWriteLock(stamp);
if (writeStamp == 0) {
// 升级失败,释放读锁,获取写锁
stampedLock.unlockRead(stamp);
writeStamp = stampedLock.writeLock();
}
try {
// 写操作
x = currentX + 1;
} finally {
stampedLock.unlockWrite(writeStamp);
}
} finally {
// 如果升级失败,这里stamp已经无效
}
}
}
5.3 StampedLock vs ReentrantReadWriteLock
性能对比(读多写少场景):
┌───────────────────────────────────────────────────────┐
│ StampedLock vs ReentrantReadWriteLock │
├──────────────┬──────────┬─────────────────────────────┤
│ 特性 │ StampedLock │ ReentrantReadWriteLock │
├──────────────┼──────────┼─────────────────────────────┤
│ 乐观读 │ ✅ │ ❌ │
│ 可重入 │ ❌ │ ✅ │
│ 条件变量 │ ❌ │ ✅ │
│ 公平锁 │ ❌ │ ✅ │
│ 读性能 │ ⭐⭐⭐⭐⭐ │ ⭐⭐⭐ │
│ 写性能 │ ⭐⭐⭐⭐ │ ⭐⭐⭐⭐ │
│ 适用场景 │ 读多写少 │ 读多写少(需要重入) │
└──────────────┴──────────┴─────────────────────────────┘
性能测试数据(1000万次读操作):
ReentrantReadWriteLock: ~500ms
StampedLock(乐观读): ~50ms(提升10倍)
六、Semaphore 信号量
6.1 Semaphore 基本概念
Semaphore 信号量:
┌───────────────────────────────────────────────────────┐
│ 信号量原理 │
├───────────────────────────────────────────────────────┤
│ │
│ 概念: │
│ - 控制同时访问资源的线程数量 │
│ - 维护一组许可证(permits) │
│ - 获取许可证后才能访问资源 │
│ │
│ 操作: │
│ - acquire(): 获取许可证(阻塞) │
│ - release(): 释放许可证 │
│ - tryAcquire(): 尝试获取(非阻塞) │
│ │
│ 应用场景: │
│ - 限流(限制并发数) │
│ - 资源池管理 │
│ - 连接池控制 │
└───────────────────────────────────────────────────────┘
6.2 Semaphore 实现原理
/**
* Semaphore 核心实现(基于AQS)
*/
public class Semaphore implements java.io.Serializable {
private final Sync sync;
/**
* 同步器(共享模式)
*/
abstract static class Sync extends AbstractQueuedSynchronizer {
Sync(int permits) {
setState(permits); // 初始化许可证数量
}
/**
* 获取许可证(共享模式)
*/
protected int tryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining)) {
return remaining;
}
}
}
/**
* 释放许可证
*/
protected boolean tryReleaseShared(int releases) {
for (;;) {
int current = getState();
int next = current + releases;
if (next < current) {
throw new Error("Maximum permit count exceeded");
}
if (compareAndSetState(current, next)) {
return true;
}
}
}
}
}
6.3 Semaphore 使用示例
/**
* Semaphore 实际应用示例
*/
@Service
@Slf4j
public class SemaphoreExample {
/**
* 场景1: 限流(限制并发请求数)
*/
public class RateLimiter {
private final Semaphore semaphore;
public RateLimiter(int maxConcurrent) {
this.semaphore = new Semaphore(maxConcurrent);
}
public <T> T execute(Supplier<T> supplier) throws InterruptedException {
semaphore.acquire(); // 获取许可证
try {
return supplier.get();
} finally {
semaphore.release(); // 释放许可证
}
}
}
/**
* 场景2: 连接池管理
*/
public class ConnectionPool {
private final Semaphore semaphore;
private final Queue<Connection> connections;
public ConnectionPool(int poolSize) {
this.semaphore = new Semaphore(poolSize);
this.connections = new ConcurrentLinkedQueue<>();
// 初始化连接池
for (int i = 0; i < poolSize; i++) {
connections.offer(createConnection());
}
}
public Connection getConnection() throws InterruptedException {
semaphore.acquire(); // 获取许可证
return connections.poll();
}
public void releaseConnection(Connection conn) {
connections.offer(conn);
semaphore.release(); // 释放许可证
}
private Connection createConnection() {
// 创建连接
return null;
}
}
/**
* 场景3: 批量任务控制
*/
public class BatchTaskController {
private final Semaphore semaphore = new Semaphore(10); // 最多10个并发
public void executeBatch(List<Runnable> tasks) {
ExecutorService executor = Executors.newFixedThreadPool(20);
for (Runnable task : tasks) {
executor.submit(() -> {
try {
semaphore.acquire();
task.run();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
semaphore.release();
}
});
}
}
}
}
七、CountDownLatch 闭锁
7.1 CountDownLatch 基本概念
CountDownLatch 闭锁:
┌───────────────────────────────────────────────────┐
│ 闭锁原理 │
├───────────────────────────────────────────────────┤
│ │
│ 概念: │
│ - 一个或多个线程等待其他线程完成操作 │
│ - 计数器递减,减到0时唤醒等待的线程 │
│ - 一次性使用(计数器不能重置) │
│ │
│ 操作: │
│ - await(): 等待计数器减到0 │
│ - countDown(): 计数器减1 │
│ │
│ 应用场景: │
│ - 等待多个任务完成 │
│ - 主线程等待子线程初始化完成 │
│ - 并行计算后汇总结果 │
└────────────────────────────────────────────────────┘
7.2 CountDownLatch 实现原理
/**
* CountDownLatch 核心实现(基于AQS)
*/
public class CountDownLatch {
private static final class Sync extends AbstractQueuedSynchronizer {
Sync(int count) {
setState(count); // 初始化计数器
}
/**
* 获取共享锁(等待计数器为0)
*/
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
/**
* 释放共享锁(计数器减1)
*/
protected boolean tryReleaseShared(int releases) {
for (;;) {
int c = getState();
if (c == 0) {
return false;
}
int nextc = c - 1;
if (compareAndSetState(c, nextc)) {
return nextc == 0; // 计数器为0时返回true
}
}
}
}
private final Sync sync;
public CountDownLatch(int count) {
if (count < 0) {
throw new IllegalArgumentException("count < 0");
}
this.sync = new Sync(count);
}
/**
* 等待计数器减到0
*/
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
/**
* 计数器减1
*/
public void countDown() {
sync.releaseShared(1);
}
}
7.3 CountDownLatch 使用示例
/**
* CountDownLatch 实际应用示例
*/
@Service
@Slf4j
public class CountDownLatchExample {
/**
* 场景1: 等待多个任务完成
*/
public void waitForTasks() throws InterruptedException {
int taskCount = 10;
CountDownLatch latch = new CountDownLatch(taskCount);
ExecutorService executor = Executors.newFixedThreadPool(taskCount);
for (int i = 0; i < taskCount; i++) {
final int taskId = i;
executor.submit(() -> {
try {
// 执行任务
doTask(taskId);
} finally {
latch.countDown(); // 任务完成,计数器减1
}
});
}
latch.await(); // 等待所有任务完成
log.info("All tasks completed");
}
/**
* 场景2: 主线程等待子线程初始化
*/
public void waitForInitialization() throws InterruptedException {
CountDownLatch initLatch = new CountDownLatch(3);
// 启动3个子线程进行初始化
for (int i = 0; i < 3; i++) {
new Thread(() -> {
try {
initialize();
} finally {
initLatch.countDown();
}
}).start();
}
initLatch.await(); // 主线程等待初始化完成
log.info("Initialization completed");
}
/**
* 场景3: 并行计算后汇总
*/
public int parallelCompute(List<Integer> data) throws InterruptedException {
int threadCount = Runtime.getRuntime().availableProcessors();
CountDownLatch latch = new CountDownLatch(threadCount);
AtomicInteger result = new AtomicInteger(0);
int chunkSize = data.size() / threadCount;
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
for (int i = 0; i < threadCount; i++) {
final int start = i * chunkSize;
final int end = (i == threadCount - 1) ? data.size() : (i + 1) * chunkSize;
executor.submit(() -> {
try {
int sum = 0;
for (int j = start; j < end; j++) {
sum += data.get(j);
}
result.addAndGet(sum);
} finally {
latch.countDown();
}
});
}
latch.await();
return result.get();
}
private void doTask(int taskId) {
// 任务逻辑
}
private void initialize() {
// 初始化逻辑
}
}
八、CyclicBarrier 循环屏障
8.1 CyclicBarrier 基本概念
CyclicBarrier 循环屏障:
┌───────────────────────────────────────────────────────┐
│ 循环屏障原理 │
├───────────────────────────────────────────────────────┤
│ │
│ 概念: │
│ - 多个线程互相等待,到达同步点后继续执行 │
│ - 可以重复使用(cyclic) │
│ - 支持屏障动作(barrier action) │
│ │
│ 与CountDownLatch的区别: │
│ - CountDownLatch: 一个或多个线程等待其他线程 │
│ - CyclicBarrier: 多个线程互相等待 │
│ - CountDownLatch: 一次性使用 │
│ - CyclicBarrier: 可重复使用 │
│ │
│ 应用场景: │
│ - 分阶段任务(多阶段并行计算) │
│ - 数据分片处理后汇总 │
│ - 多线程测试 │
└─────────────────────────────────────────────────────┘
8.2 CyclicBarrier 实现原理
/**
* CyclicBarrier 核心实现
*/
public class CyclicBarrier {
private static class Generation {
boolean broken = false;
}
private final ReentrantLock lock = new ReentrantLock();
private final Condition trip = lock.newCondition();
private final int parties; // 参与的线程数
private final Runnable barrierCommand; // 屏障动作
private Generation generation = new Generation();
private int count; // 当前等待的线程数
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) {
throw new IllegalArgumentException();
}
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
/**
* 等待到达屏障
*/
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe);
}
}
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException, TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
final Generation g = generation;
if (g.broken) {
throw new BrokenBarrierException();
}
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
int index = --count;
if (index == 0) {
// 最后一个线程到达,执行屏障动作
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null) {
command.run();
}
ranAction = true;
// 重置屏障,唤醒所有等待的线程
nextGeneration();
return 0;
} finally {
if (!ranAction) {
breakBarrier();
}
}
}
// 等待其他线程到达
for (;;) {
try {
if (!timed) {
trip.await();
} else if (nanos > 0L) {
nanos = trip.awaitNanos(nanos);
}
} catch (InterruptedException ie) {
if (g == generation && !g.broken) {
breakBarrier();
throw ie;
} else {
Thread.currentThread().interrupt();
}
}
if (g.broken) {
throw new BrokenBarrierException();
}
if (g != generation) {
return index;
}
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
/**
* 重置屏障
*/
private void nextGeneration() {
trip.signalAll();
count = parties;
generation = new Generation();
}
/**
* 破坏屏障
*/
private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}
}
8.3 CyclicBarrier 使用示例
/**
* CyclicBarrier 实际应用示例
*/
@Service
@Slf4j
public class CyclicBarrierExample {
/**
* 场景1: 分阶段并行计算
*/
public void phasedComputation() throws BrokenBarrierException, InterruptedException {
int threadCount = 4;
CyclicBarrier barrier = new CyclicBarrier(threadCount, () -> {
log.info("All threads reached barrier, continue...");
});
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
for (int i = 0; i < threadCount; i++) {
final int threadId = i;
executor.submit(() -> {
try {
// 阶段1
log.info("Thread {} phase 1", threadId);
barrier.await();
// 阶段2
log.info("Thread {} phase 2", threadId);
barrier.await();
// 阶段3
log.info("Thread {} phase 3", threadId);
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
Thread.currentThread().interrupt();
}
});
}
}
/**
* 场景2: 数据分片处理
*/
public void dataChunkProcessing(List<Integer> data) throws BrokenBarrierException, InterruptedException {
int chunkCount = 4;
CyclicBarrier barrier = new CyclicBarrier(chunkCount + 1); // +1 for main thread
List<List<Integer>> chunks = partition(data, chunkCount);
AtomicInteger totalSum = new AtomicInteger(0);
ExecutorService executor = Executors.newFixedThreadPool(chunkCount);
for (List<Integer> chunk : chunks) {
executor.submit(() -> {
try {
int sum = chunk.stream().mapToInt(Integer::intValue).sum();
totalSum.addAndGet(sum);
barrier.await(); // 等待所有分片处理完成
} catch (InterruptedException | BrokenBarrierException e) {
Thread.currentThread().interrupt();
}
});
}
barrier.await(); // 主线程等待
log.info("Total sum: {}", totalSum.get());
}
private List<List<Integer>> partition(List<Integer> data, int chunks) {
// 数据分片逻辑
return null;
}
}
九、Phaser 阶段器
9.1 Phaser 基本概念
Phaser 阶段器(JDK 7+):
┌──────────────────────────────────────────────────┐
│ 阶段器特性 │
├──────────────────────────────────────────────────┤
│ │
│ 概念: │
│ - 可重用的同步屏障 │
│ - 支持分阶段同步 │
│ - 支持动态注册和注销线程 │
│ │
│ 优势: │
│ - 比CyclicBarrier更灵活 │
- 支持动态调整参与线程数 │
- 支持分层结构 │
│ │
│ 应用场景: │
│ - 复杂的分阶段任务 │
│ - 动态线程同步 │
│ - 游戏开发(多阶段游戏逻辑) │
└──────────────────────────────────────────────────┘
9.2 Phaser 使用示例
/**
* Phaser 实际应用示例
*/
@Service
@Slf4j
public class PhaserExample {
/**
* 场景1: 分阶段任务
*/
public void phasedTask() {
Phaser phaser = new Phaser(3); // 3个参与线程
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
final int taskId = i;
executor.submit(() -> {
// 阶段0
log.info("Task {} phase 0", taskId);
phaser.arriveAndAwaitAdvance();
// 阶段1
log.info("Task {} phase 1", taskId);
phaser.arriveAndAwaitAdvance();
// 阶段2
log.info("Task {} phase 2", taskId);
phaser.arriveAndAwaitAdvance();
});
}
}
/**
* 场景2: 动态注册线程
*/
public void dynamicRegistration() {
Phaser phaser = new Phaser(1); // 主线程注册
for (int i = 0; i < 3; i++) {
phaser.register(); // 动态注册
final int taskId = i;
new Thread(() -> {
log.info("Task {} started", taskId);
phaser.arriveAndAwaitAdvance();
log.info("Task {} completed", taskId);
phaser.arriveAndDeregister(); // 注销
}).start();
}
phaser.arriveAndAwaitAdvance(); // 等待所有任务完成
}
/**
* 场景3: 分层Phaser
*/
public void hierarchicalPhaser() {
Phaser rootPhaser = new Phaser(3);
// 创建子Phaser
Phaser childPhaser1 = new Phaser(rootPhaser, 2);
Phaser childPhaser2 = new Phaser(rootPhaser, 2);
// 使用子Phaser
ExecutorService executor = Executors.newFixedThreadPool(4);
executor.submit(() -> {
childPhaser1.arriveAndAwaitAdvance();
log.info("Child task 1 completed");
});
executor.submit(() -> {
childPhaser1.arriveAndAwaitAdvance();
log.info("Child task 2 completed");
});
executor.submit(() -> {
childPhaser2.arriveAndAwaitAdvance();
log.info("Child task 3 completed");
});
executor.submit(() -> {
childPhaser2.arriveAndAwaitAdvance();
log.info("Child task 4 completed");
});
}
}
十、LockSupport 锁支持
10.1 LockSupport 基本概念
LockSupport 锁支持:
┌──────────────────────────────────────────────────┐
│ LockSupport 特点 │
├─────────────────────────────────────────────────┤
│ │
│ 功能: │
│ - 线程阻塞和唤醒的基础工具 │
│ - 每个线程都有一个许可(permit) │
│ - park(): 阻塞线程(如果许可不可用) │
│ - unpark(): 唤醒线程(使许可可用) │
│ │
│ 优势: │
│ - 更精确的线程控制 │
│ - 不会抛出InterruptedException │
│ - 支持先unpark后park(许可可以提前发放) │
│ │
│ 应用: │
│ - AQS的底层实现 │
│ - 自定义同步工具 │
└──────────────────────────────────────────────────┘
10.2 LockSupport 使用示例
/**
* LockSupport 使用示例
*/
public class LockSupportExample {
/**
* 基本用法
*/
public void basicUsage() {
Thread thread = new Thread(() -> {
System.out.println("Thread waiting...");
LockSupport.park(); // 阻塞线程
System.out.println("Thread resumed");
});
thread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
LockSupport.unpark(thread); // 唤醒线程
}
/**
* 先unpark后park(许可可以提前发放)
*/
public void unparkBeforePark() {
Thread thread = new Thread(() -> {
try {
Thread.sleep(1000); // 延迟1秒
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Thread trying to park...");
LockSupport.park(); // 不会阻塞,因为许可已经可用
System.out.println("Thread continued");
});
thread.start();
LockSupport.unpark(thread); // 先发放许可
}
/**
* 自定义锁实现(基于LockSupport)
*/
public class CustomLock {
private volatile Thread owner;
private final Queue<Thread> waitQueue = new ConcurrentLinkedQueue<>();
public void lock() {
Thread currentThread = Thread.currentThread();
if (owner == null && compareAndSetOwner(null, currentThread)) {
return; // 获取锁成功
}
// 获取锁失败,加入等待队列
waitQueue.offer(currentThread);
// 自旋等待
while (owner != currentThread) {
LockSupport.park(); // 阻塞
}
}
public void unlock() {
Thread currentThread = Thread.currentThread();
if (owner != currentThread) {
throw new IllegalMonitorStateException();
}
owner = null;
// 唤醒等待队列中的线程
Thread nextThread = waitQueue.poll();
if (nextThread != null) {
LockSupport.unpark(nextThread);
}
}
private boolean compareAndSetOwner(Thread expect, Thread update) {
// CAS操作
return false;
}
}
}
十一、原子类(Atomic Classes)
11.1 原子类体系
Java原子类体系:
┌───────────────────────────────────────────────────────┐
│ 原子类分类 │
├───────────────────────────────────────────────────────┤
│ │
│ 1. 基本类型原子类: │
│ - AtomicInteger │
│ - AtomicLong │
│ - AtomicBoolean │
│ │
│ 2. 引用类型原子类: │
│ - AtomicReference │
│ - AtomicStampedReference(带版本号) │
│ - AtomicMarkableReference(带标记位) │
│ │
│ 3. 数组类型原子类: │
│ - AtomicIntegerArray │
│ - AtomicLongArray │
│ - AtomicReferenceArray │
│ │
│ 4. 字段更新器: │
│ - AtomicIntegerFieldUpdater │
│ - AtomicLongFieldUpdater │
│ - AtomicReferenceFieldUpdater │
│ │
│ 5. 累加器(JDK 8+): │
│ - LongAdder │
│ - DoubleAdder │
│ - LongAccumulator │
│ - DoubleAccumulator │
└───────────────────────────────────────────────────────┘
11.2 AtomicInteger 深度解析
/**
* AtomicInteger 核心实现原理
*/
public class AtomicInteger extends Number implements java.io.Serializable {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset(
AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) {
throw new Error(ex);
}
}
private volatile int value;
/**
* CAS操作
*/
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
/**
* 获取并增加
*/
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
/**
* 增加并获取
*/
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
/**
* 原子更新(函数式)
*/
public final int updateAndGet(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return next;
}
}
11.3 LongAdder 高性能累加器
/**
* LongAdder 高性能累加器(JDK 8+)
*
* 原理: 分段累加,减少CAS竞争
*/
public class LongAdderExample {
/**
* LongAdder vs AtomicLong 性能对比
*/
public void performanceComparison() {
AtomicLong atomicLong = new AtomicLong(0);
LongAdder longAdder = new LongAdder();
int threadCount = 10;
int operations = 1000000;
// AtomicLong测试
long start = System.currentTimeMillis();
ExecutorService executor1 = Executors.newFixedThreadPool(threadCount);
for (int i = 0; i < threadCount; i++) {
executor1.submit(() -> {
for (int j = 0; j < operations; j++) {
atomicLong.incrementAndGet();
}
});
}
executor1.shutdown();
try {
executor1.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
long atomicTime = System.currentTimeMillis() - start;
// LongAdder测试
start = System.currentTimeMillis();
ExecutorService executor2 = Executors.newFixedThreadPool(threadCount);
for (int i = 0; i < threadCount; i++) {
executor2.submit(() -> {
for (int j = 0; j < operations; j++) {
longAdder.increment();
}
});
}
executor2.shutdown();
try {
executor2.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
long adderTime = System.currentTimeMillis() - start;
System.out.println("AtomicLong time: " + atomicTime + "ms");
System.out.println("LongAdder time: " + adderTime + "ms");
// LongAdder在高并发下性能通常优于AtomicLong
}
/**
* LongAdder 实现原理(简化版)
*/
public class LongAdderCore {
private volatile Cell[] cells; // 分段数组
private volatile long base; // 基础值
/**
* 累加
*/
public void increment() {
Cell[] as = cells;
Cell a;
long b = base, v;
if (as != null && (a = as[getProbe() & (as.length - 1)]) != null) {
// 使用分段累加
if (!a.cas(v = a.value, v + 1)) {
longAccumulate(1L, null, true);
}
} else if (casBase(b = base, b + 1)) {
// 使用base累加
return;
} else {
longAccumulate(1L, null, false);
}
}
/**
* 获取总和
*/
public long sum() {
Cell[] as = cells;
long sum = base;
if (as != null) {
for (Cell a : as) {
if (a != null) {
sum += a.value;
}
}
}
return sum;
}
}
}
十二、锁的性能对比
12.1 性能测试代码
/**
* 锁性能基准测试(JMH)
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
public class LockPerformanceBenchmark {
private int counter = 0;
private final Object syncLock = new Object();
private final ReentrantLock reentrantLock = new ReentrantLock();
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private final StampedLock stampedLock = new StampedLock();
private final AtomicInteger atomicInt = new AtomicInteger(0);
/**
* synchronized性能
*/
@Benchmark
public void testSynchronized() {
synchronized (syncLock) {
counter++;
}
}
/**
* ReentrantLock性能
*/
@Benchmark
public void testReentrantLock() {
reentrantLock.lock();
try {
counter++;
} finally {
reentrantLock.unlock();
}
}
/**
* ReentrantReadWriteLock写锁性能
*/
@Benchmark
public void testReadWriteLockWrite() {
rwLock.writeLock().lock();
try {
counter++;
} finally {
rwLock.writeLock().unlock();
}
}
/**
* StampedLock写锁性能
*/
@Benchmark
public void testStampedLockWrite() {
long stamp = stampedLock.writeLock();
try {
counter++;
} finally {
stampedLock.unlockWrite(stamp);
}
}
/**
* CAS操作性能
*/
@Benchmark
public void testCAS() {
atomicInt.incrementAndGet();
}
}
12.2 性能测试结果
性能测试结果(单线程,1000万次操作):
┌────────────────────────────────────────────────────────┐
│ 操作耗时(毫秒) │
├──────────────┬──────────┬──────────┬───────────────────┤
│ 锁类型 │ 无竞争 │ 低竞争 │ 高竞争 │
├──────────────┼──────────┼──────────┼───────────────────┤
│ synchronized │ ~100ms │ ~200ms │ ~500ms │
│ ReentrantLock│ ~150ms │ ~250ms │ ~600ms │
│ ReadWriteLock│ ~200ms │ ~300ms │ ~700ms │
│ StampedLock │ ~180ms │ ~280ms │ ~650ms │
│ CAS │ ~50ms │ ~100ms │ ~300ms(自旋) │
└──────────────┴──────────┴──────────┴───────────────────┘
性能分析:
1. 无竞争场景:
- CAS最快(~50ms),无锁操作
- synchronized次之(~100ms),偏向锁优化
- ReentrantLock较慢(~150ms),方法调用开销
2. 低竞争场景:
- CAS仍然最快(~100ms)
- synchronized中等(~200ms),轻量级锁
- ReentrantLock较慢(~250ms)
3. 高竞争场景:
- CAS性能下降(~300ms),大量自旋
- synchronized性能下降(~500ms),重量级锁
- ReentrantLock性能下降(~600ms),线程阻塞
12.3 读写锁性能对比
读写锁性能对比(读多写少场景,读:写 = 10:1):
┌────────────────────────────────────────────────────┐
│ 性能对比 │
├──────────────┬──────────┬──────────────────────────┤
│ 锁类型 │ QPS │ 说明 │
├──────────────┼──────────┼──────────────────────────┤
│ synchronized │ 1,000 │ 所有操作串行 │
│ ReentrantLock│ 1,000 │ 所有操作串行 │
│ ReadWriteLock│ 5,000 │ 读操作并发(10倍提升) │
│ StampedLock │ 8,000 │ 乐观读性能更高(16倍提升) │
└──────────────┴──────────┴──────────────────────────┘
十三、最佳实践与选择指南
13.1 锁选择决策树
锁选择决策树:
开始
│
├─ 是否需要跨进程/跨服务器?
│ ├─ 是 → 使用分布式锁(Redis/ZooKeeper/etcd)
│ └─ 否 → 继续
│
├─ 读多写少?
│ ├─ 是 → 使用读写锁(ReentrantReadWriteLock/StampedLock)
│ └─ 否 → 继续
│
├─ 需要高级特性(可中断、超时、条件变量)?
│ ├─ 是 → 使用ReentrantLock
│ └─ 否 → 继续
│
├─ 需要限制并发数?
│ ├─ 是 → 使用Semaphore
│ └─ 否 → 继续
│
├─ 需要等待多个任务完成?
│ ├─ 是 → 使用CountDownLatch
│ └─ 否 → 继续
│
├─ 需要分阶段同步?
│ ├─ 是 → 使用CyclicBarrier/Phaser
│ └─ 否 → 继续
│
├─ 只需要原子操作?
│ ├─ 是 → 使用原子类(AtomicInteger等)
│ └─ 否 → 使用synchronized
13.2 性能优化建议
性能优化建议:
1. 减少锁的持有时间
✅ 只锁必要的代码块
❌ 不要在锁内执行耗时操作
2. 减小锁的粒度
✅ 使用细粒度锁
❌ 避免粗粒度锁
3. 减少锁的竞争
✅ 使用分段锁
✅ 使用读写锁(读多写少)
✅ 使用无锁数据结构
4. 合理选择锁类型
✅ 读多写少 → 读写锁
✅ 只需要原子操作 → 原子类
✅ 需要高级特性 → ReentrantLock
✅ 简单场景 → synchronized
5. 避免死锁
✅ 统一锁的获取顺序
✅ 设置锁超时时间
✅ 使用tryLock()
13.3 常见陷阱与避免方法
常见陷阱:
1. 锁泄漏
❌ 异常时未释放锁
✅ 使用try-finally确保释放
2. 死锁
❌ 多个锁的获取顺序不一致
✅ 统一锁的获取顺序
3. 活锁
❌ 线程互相谦让
✅ 引入随机等待时间
4. 过度使用锁
❌ 所有操作都加锁
✅ 只在必要时加锁
5. 锁的粒度不当
❌ 锁整个方法
✅ 只锁必要的代码块
6. 忽略ABA问题
❌ 直接使用CAS
✅ 使用版本号或AtomicStampedReference
总结
Java锁体系总结
Java锁体系完整总结:
┌─────────────────────────────────────────────────────┐
│ 锁类型与适用场景 │
├──────────────┬──────────┬───────────────────────────┤
│ 锁类型 │ 性能 │ 适用场景 │
├──────────────┼──────────┼───────────────────────────┤
│ synchronized │ ⭐⭐⭐⭐ │ 通用场景,简单易用 │
│ ReentrantLock│ ⭐⭐⭐ │ 需要高级特性 │
│ ReadWriteLock│ ⭐⭐⭐⭐ │ 读多写少 │
│ StampedLock │ ⭐⭐⭐⭐⭐│ 读多写少(JDK8+) │
│ Semaphore │ ⭐⭐⭐ │ 限流、资源控制 │
│ CountDownLatch│ ⭐⭐⭐⭐ │ 等待多个任务完成 │
│ CyclicBarrier│ ⭐⭐⭐ │ 分阶段同步 │
│ Phaser │ ⭐⭐⭐ │ 复杂分阶段同步 │
│ AtomicInteger│ ⭐⭐⭐⭐⭐│ 计数器、状态标志 │
└──────────────┴──────────┴────────────────────────────┘
核心要点
✅ 根据场景选择合适的锁类型
✅ 减少锁的持有时间和粒度
✅ 避免死锁和锁泄漏
✅ 合理使用读写锁优化性能
✅ 在高并发场景下考虑无锁编程
✅ 监控锁的使用情况,及时优化
参考资源:
8万+

被折叠的 条评论
为什么被折叠?



