在多线程编程中,锁是保障数据一致性的基石。Java通过多种锁机制实现线程同步
分类标准 | 典型代表 | 核心差异 |
---|---|---|
实现方式 | synchronized/ReentrantLock | JVM原生 vs 显式API |
锁粒度 | 读写锁/分段锁 | 资源控制粒度差异 |
锁状态 | 公平锁/非公平锁 | 获取顺序策略 |
操作方式 | 自旋锁/阻塞锁 | 等待策略差异 |
底层实现:
monitorenter/monitorexit
控制加锁释放代码示例:
public class Counter {
private int count = 0;
// 同步方法 - 锁定当前对象实例
public synchronized void increment() {
count++; // 原子性递增操作
}
// 同步代码块 - 锁定指定对象
public void batchProcess() {
synchronized(this) { // 显式锁定当前实例
// 临界区操作
}
}
// 静态同步方法 - 锁定类对象
public static synchronized void staticMethod() {
// 操作静态资源
}
}
特性说明:
核心优势:
ReentrantLock lock = new ReentrantLock(true); // 公平锁
lock.lock(); // 主动获取锁
try {
// 临界区操作
} finally {
lock.unlock(); // 必须手动释放
}
特性说明:
ReentrantLock进阶使用:
// 尝试获取锁(带超时)
boolean acquired = lock.tryLock(1, TimeUnit.SECONDS);
if(acquired) {
try {
// 临界区操作
} finally {
lock.unlock();
}
} else {
// 处理获取锁失败场景
}
// 条件变量控制线程通信
Condition condition = lock.newCondition();
condition.await(); // 线程等待
condition.signal(); // 唤醒等待线程
性能对比:
场景 | 读写锁吞吐量 | 普通锁吞吐量 |
---|---|---|
读多写少 | 10倍+ | 基准值 |
读写均衡 | 1.2倍 | 基准值 |
写多读少 | 0.8倍 | 基准值 |
代码示例:
ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
Lock readLock = rwLock.readLock(); // 共享读锁
Lock writeLock = rwLock.writeLock(); // 独占写锁
// 读操作(允许多线程并发)
readLock.lock();
try {
// 读取共享数据
} finally {
readLock.unlock();
}
// 写操作(排他性访问)
writeLock.lock();
try {
// 修改共享数据
} finally {
writeLock.unlock();
}
特性说明:
CAS实现原理:
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
// 通过CAS操作实现原子递增
}
代码示例:
AtomicInteger atomicInt = new AtomicInteger(0);
int current = atomicInt.getAndIncrement(); // 原子递增并返回旧值
AtomicReference<String> atomicRef = new AtomicReference<>();
atomicRef.compareAndSet("oldValue", "newValue"); // CAS更新引用
特性说明:
核心代码:
public class SpinLock {
private AtomicBoolean locked = new AtomicBoolean(false);
public void lock() {
while(!locked.compareAndSet(false, true)) {
// 自旋等待(不释放CPU)
}
}
public void unlock() {
locked.set(false);
}
}
特性说明:
ConcurrentHashMap实现原理:
+-------------------+
| Segment 0 |
| +-------------+ |
| | HashEntry | |
| +-------------+ |
+-------------------+
| Segment 1 |
| +-------------+ |
| | HashEntry | |
| +-------------+ |
+-------------------+
代码示例:
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
map.putIfAbsent("key", "value"); // 分段锁控制并发
特性说明:
版本号机制:
public class OptimisticLock {
private int version = 0;
public boolean update() {
int currentVersion = version;
// 模拟业务处理
if(version == currentVersion) {
version++;
return true;
}
return false;
}
}
CAS实现:
public class AtomicCounter {
private AtomicInteger count = new AtomicInteger(0);
public int increment() {
int current;
do {
current = count.get();
} while(!count.compareAndSet(current, current+1));
return current+1;
}
}
特性说明:
实现原理:
public class LockFreeStack<T> {
private AtomicReference<Node<T>> top = new AtomicReference<>();
public void push(T value) {
Node<T> newHead = new Node<>(value);
Node<T> oldHead;
do {
oldHead = top.get();
newHead.next = oldHead;
} while(!top.compareAndSet(oldHead, newHead));
}
public T pop() {
Node<T> oldHead;
Node<T> newHead;
do {
oldHead = top.get();
if(oldHead == null) return null;
newHead = oldHead.next;
} while(!top.compareAndSet(oldHead, newHead));
return oldHead.value;
}
}
特性说明:
是否需要高并发读?
├─ 是 → 读写锁
└─ 否 → 是否需要重入?
├─ 是 → ReentrantLock
└─ 否 → 原子锁
锁类型 | 吞吐量(ops/s) | 延迟(μs) | 适用场景 |
---|---|---|---|
ReentrantLock | 500,000 | 2.1 | 复杂同步控制 |
ReadWriteLock | 2,000,000 | 0.8 | 读多写少 |
AtomicInteger | 10,000,000 | 0.2 | 计数器/状态标记 |
Synchronized | 300,000 | 5.3 | 简单同步需求 |
Java锁机制已形成完整的生态系统,从基础的synchronized到高阶的StampedLock,每种锁都有其独特的应用场景。开发者需深入理解锁的底层原理,结合业务特征选择合适的锁策略。在云原生和分布式系统普及的今天,掌握锁的选型与优化技巧,是构建高性能并发系统的关键所在。