ReentrantLock源码学习总结 (二)
ReentrantLock 示例
private ReentrantLock lock = new ReentrantLock(true);
public void f(){
try {
lock.lock();
//do something
}
finally {
lock.unlock();
}
}
源码解析(公平锁-unlock流程)
ReentrantLock#unlock()
public void unlock() {
sync.release(1);
}
AbstractQueuedSynchronizer#release(int arg)
public final boolean release(int arg) {
//尝试释放锁,只有当 state == 0 才会释放成功
if (tryRelease(arg)) {
//释放成功之后,查看head节点,如果head节点不为 null,并且,head节点不为0 (可能为 -1)
Node h = head;
if (h != null && h.waitStatus != 0)
//unpark 线程
unparkSuccessor(h);
return true;
}
return false;
}
ReentrantLock.Sync#tryRelease(int arg)
protected final boolean tryRelease(int releases) {
//state - releases,上锁之后,state > 0,所以释放锁要减掉
int c = getState() - releases;
//如果当前线程并不是持有锁的线程,不能乱释放锁,直接给你抛个异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
//释放标志
boolean free = false;
//由于是可重入锁,所以当 c == 0 的情况下才真正释放完成
if (c == 0) {
free = true;
//设置当前线程为空
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
AbstractQueuedSynchronizer#unparkSuccessor(Node node)
private void unparkSuccessor(Node node) {
//获取head node节点的 waitStatus , < 0(-1) 就CAS 改回 0
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
//找到下一个节点
Node s = node.next;
//如果下一个节点为null,或者 已经取消抢锁了,继续往下找
if (s == null || s.waitStatus > 0) {
s = null;
//从尾部向前遍历,如果 waitStatus<=0 就赋值给 s,这样保证最前边的一个waitStatus<=0的线程可以唤醒。
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
//如果下一个节点不为 null,直接 unpark 线程,对应代码就是AbstractQueuedSynchronizer#acquireQueued(Node node, int arg) 中 的for(;;),这样线程唤醒之后,就会尝试再去获取锁了。
if (s != null)
LockSupport.unpark(s.thread);
}
总结
释放锁的流程比较简单,就是讲 state
减去1,然后去队列里面找下一个节点,最后执行 unpark
方法唤醒线程。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
2017-10-17 Maven的一些基本命令