简介:本文深入解析ReentrantLock的核心机制,涵盖其基于AQS的锁状态管理、公平/非公平锁实现、可重入特性及线程阻塞唤醒流程。通过代码示例与流程图解,帮助开发者理解其设计原理与适用场景,为高并发场景下的锁优化提供技术参考。
ReentrantLock是Java并发包(java.util.concurrent.locks)中提供的显式锁实现,属于可重入互斥锁(Reentrant Mutual Exclusion Lock)。与隐式锁(synchronized关键字)不同,它通过代码显式控制锁的获取与释放,提供更灵活的并发控制能力。其核心特性包括:
该锁的实现完全基于AbstractQueuedSynchronizer(AQS)框架,通过继承AQS并实现其模板方法,构建出完整的锁竞争与状态管理机制。
在Java并发编程中,隐式锁(synchronized)存在以下局限性:
ReentrantLock的出现解决了这些问题:
典型应用场景包括:
ReentrantLock的底层完全依赖AQS实现,其核心组件包括:
private volatile int state; // 0表示无锁,>0表示锁被持有次数
ReentrantLock通过两个内部类实现AQS模板方法:
abstract static class Sync extends AbstractQueuedSynchronizer {abstract void lock();protected final boolean tryAcquire(int acquires) {// 子类实现具体获取逻辑}protected final boolean tryRelease(int releases) {// 子类实现具体释放逻辑}}// 非公平锁实现static final class NonfairSync extends Sync {final void lock() {if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1); // 调用AQS通用逻辑}}// 公平锁实现static final class FairSync extends Sync {final void lock() {acquire(1); // 直接进入队列排队}}
public void lock() {// 1. 尝试CAS抢锁(插队逻辑)if (compareAndSetState(0, 1)) {setExclusiveOwnerThread(Thread.currentThread());} else {// 2. 抢锁失败,进入AQS通用流程acquire(1);}}// AQS.acquire()实现public final void acquire(int arg) {if (!tryAcquire(arg) && // 尝试获取锁acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // 入队并阻塞selfInterrupt();}
关键步骤:
public void unlock() {sync.release(1);}// AQS.release()实现public final boolean release(int arg) {if (tryRelease(arg)) { // 修改stateNode h = head;if (h != null && h.waitStatus != 0)unparkSuccessor(h); // 唤醒后继节点return true;}return false;}
释放逻辑:
// NonfairSync.tryAcquire()实现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;}
重入机制:
class OrderService {private final ReentrantLock lock = new ReentrantLock(true); // 公平锁public void processOrder(Order order) {lock.lock();try {// 订单处理逻辑} finally {lock.unlock();}}}
优势:
public boolean tryTransfer(Account from, Account to, BigDecimal amount, long timeout) {ReentrantLock lock = new ReentrantLock();if (lock.tryLock(timeout, TimeUnit.MILLISECONDS)) {try {// 转账操作return true;} finally {lock.unlock();}}return false; // 超时失败}
价值:
| 特性 | synchronized | ReentrantLock |
|---|---|---|
| 获取方式 | 隐式 | 显式 |
| 公平性 | 非公平 | 可选公平/非公平 |
| 超时控制 | 不支持 | 支持 |
| 可中断性 | 不支持 | 支持 |
| 条件变量 | Object.wait()/notify() | Condition.await()/signal() |
| 性能 | JDK6后优化接近 | 高并发下略有优势 |
// 错误示范lock.lock();doSomething();lock.unlock(); // 可能因异常未执行// 正确做法lock.lock();try {doSomething();} finally {lock.unlock();}
// 错误示范:A锁内获取B锁,B锁内又尝试获取A锁public void methodA() {lockA.lock();try {methodB(); // 可能导致死锁} finally {lockA.unlock();}}public void methodB() {lockB.lock();try {lockA.lock(); // 死锁风险} finally {lockB.unlock();}}
ReentrantLock作为Java并发编程的核心组件,通过AQS框架实现了灵活的锁机制。其核心价值在于:
适用边界:
通过深入理解ReentrantLock的机制,开发者可以更高效地设计高并发系统,在保证线程安全的同时最大化系统吞吐量。