重入锁 ReentrantLock 原理
类结构
public class ReentrantLock implements Lock, java.io.Serializable {
// 有个 Sync 的属性(是内部类 Sync,就是 AQS)
private final Sync sync;
// Sync 继承 AQS
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();
}
// 获取锁,底层是通过 Sync 实现的
public void lock() {
sync.lock();
}
// 释放锁,也是通过 Sync 实现的
public void unlock() {
sync.release(1);
}
}
公平锁
// java.util.concurrent.locks.ReentrantLock.FairSync#lock
final void lock() {
acquire(1);
}
// java.util.concurrent.locks.AbstractQueuedSynchronizer#acquire
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
//java.util.concurrent.locks.AbstractQueuedSynchronizer#tryAcquire
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
// java.util.concurrent.locks.ReentrantLock.FairSync#tryAcquire
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState(); // 资源状态
if (c == 0) { // 如果是0,表示当前没有别的线程获取
if (!hasQueuedPredecessors() && // AQS 的方法,看当前队列是否已经有节点了,如果没有才尝试获取锁,不然乖乖排队。非公平锁不会有这个判断
compareAndSetState(0, acquires) // 尝试获取锁
) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) { // 如果 state != 0,看看持有锁的线程是不是当前线程,重入锁的体现
int nextc = c + acquires; // state +1,state >0 说明锁被持有,并且被重复持有,重入
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
非公平锁
// java.util.concurrent.locks.ReentrantLock.NonfairSync#lock
final void lock() {
if (compareAndSetState(0, 1)) // 资源状态改成 1,非公平锁一进来就尝试抢锁
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
// java.util.concurrent.locks.AbstractQueuedSynchronizer#acquire
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
// java.util.concurrent.locks.AbstractQueuedSynchronizer#tryAcquire
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
// java.util.concurrent.locks.ReentrantLock.NonfairSync#tryAcquire
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
// java.util.concurrent.locks.ReentrantLock.Sync#nonfairTryAcquire
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;
}
要是有 AQS 的知识,分析 ReentrantLock 还是非常容易的,AQS 在上一篇文章中
看得出来公平和非公平锁的唯一区别就是,非公平锁要插队(插队两次)
释放锁
锁的释放也是依赖 Sync 实现的,也是比较简单的,就是维护 state
没有维护队列,释放锁后当前线程的节点要出队,队列的维护是 AQS 实现的
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
分类:
JAVA - JUC
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南