发布于2026-07-14 阅读(0)
扫一扫,手机访问
全路径名:ja va.util.concurrent.locks.ReentrantLock,类定义如下:

/**
* @since 1.5
*/
public class ReentrantLock implements Lock, ja va.io.Serializable {
...
}
ReentrantLock 实现了 Lock 接口,从 JDK1.5 开始引入。这个类大家平时用得不少,但真正理解其内部机制的,恐怕不多。
使用上,ReentrantLock 提供了两种锁机制:公平锁和非公平锁。默认的无参构造方法 ReentrantLock() 创建的是非公平锁;如果想用公平锁,可以通过有参构造 ReentrantLock(boolean fair) 来选择。具体实现靠的是两个内部类:FairSync 和 NonfairSync,它们都是抽象内部类 Sync 的子类,而 Sync 又继承了 AbstractQueuedSynchronizer。源码如下:
public class ReentrantLock implements Lock, ja va.io.Serializable {
...
private final Sync sync;
...
abstract static class Sync extends AbstractQueuedSynchronizer {...}
static final class NonfairSync extends Sync {...}
static final class FairSync extends Sync {...}
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
public void lock() {
sync.lock();
}
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
public void unlock() {
sync.release(1);
}
public Condition newCondition() {
return sync.newCondition();
}
...
}
Lock 接口定义了5个方法,源码如下:
public interface Lock {
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
}
接下来,我们通过 Lock 接口的 lock() 方法实现,来看看 ReentrantLock 是如何实现公平锁的。先讲思路再看代码,会容易得多。
要公平,就得有先来后到。打个比方,就像超市购物结账:如果结账时恰好没人,那就直接结账——拿到锁;如果已经有人在排队,那就排到队伍后面,等轮到你的时候才能结账——拿到锁。很直观,对吧?
ReentrantLock 的内部类 FairSync 负责实现公平锁机制。它继承了 Sync,而 Sync 又继承了 AbstractQueuedSynchronizer。下面是 lock() 相关源码:
static final class FairSync extends Sync {
final void lock() {
acquire(1);
}
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 abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements ja va.io.Serializable {
...
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
...
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
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);
}
}
}
FairSync 的 lock() 方法直接调用 AbstractQueuedSynchronizer 的 acquire() 去获取锁。在 acquire() 中,先通过 FairSync 的 tryAcquire() 处理“没人排队”的场景:
int c = getState():获取 AbstractQueuedSynchronizer 的状态值。c = 0 表示目前没有线程持有锁。!hasQueuedPredecessors():判断是否有其他线程在排队,如果没有,才能直接尝试获取。compareAndSetState(0, acquires):通过 CAS(Compare and Swap)这个 CPU 硬件原语来原子地获取锁。setExclusiveOwnerThread(current):成功获取锁后,将当前线程绑定为独占所有者。else if (current == getExclusiveOwnerThread()):如果锁已经被当前线程持有,那就把状态 c 加 1。这正是 ReentrantLock 可重入性的体现——同一个线程在未释放锁时可以重复加锁,每次状态加 1。如果没人排队但抢锁失败(比如 CAS 被其他线程抢先),那就进入排队场景。acquire() 方法的后续逻辑:
for (;;):无限循环,直到获取锁。if (p == head && tryAcquire(arg)):只有排在队列首位的线程才有资格竞争锁。这里的 p 就是当前节点的前驱节点(理论上应该是 head)。parkAndCheckInterrupt():如果没抢到,线程就会被阻塞,这里不做深入讨论。搞懂了公平锁,非公平锁就简单多了。非公平锁由 NonfairSync 实现:
static final class NonfairSync extends Sync {
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
abstract static class Sync extends AbstractQueuedSynchronizer {
...
final boolean nonfairTryAcquire(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) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
...
}
从源码可以清晰看到:上来就直接调用 compareAndSetState(0, 1) 抢锁,根本不管有没有人在排队。这就是非公平锁的核心——谁抢到算谁的,不讲先来后到。
上一篇:MyBatis关联查询的实现
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8