ReentrantLock非公平锁原理详解
创作时间:
作者:
@小白创作中心
ReentrantLock非公平锁原理详解
引用
CSDN
1.
https://blog.csdn.net/m0_62645012/article/details/138963528
ReentrantLock是非阻塞锁的一种实现,它提供了比synchronized更灵活的锁获取方式。本文将深入探讨ReentrantLock的非公平锁实现原理,包括加锁和解锁的具体过程。
ReentrantLock有两种锁:公平锁和非公平锁。从构造器来看,ReentrantLock默认实现是非公平锁。
1. 非公平锁原理
加锁过程
当没有竞争时,非公平锁会直接将exclusiveOwnerThread
设置为当前线程,并将state
设置为1。
当有多个线程竞争锁时,线程会通过acquire
方法尝试获取锁:
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
如果CAS操作失败,线程会进入等待队列:
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
线程进入acquireQueued
方法后,会不断尝试获取锁:
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;
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
如果线程在队列中,会通过shouldParkAfterFailedAcquire
方法检查是否需要阻塞:
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
return true;
if (ws > 0) {
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
如果需要阻塞,线程会通过parkAndCheckInterrupt
方法进入等待状态:
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
解锁过程
当持有锁的线程释放锁时,会调用release
方法:
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
如果释放成功,会唤醒等待队列中的下一个线程:
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
注意事项
- 是否需要唤醒线程是由当前节点的前驱节点的
waitStatus
决定的,而不是本节点的waitStatus
。 - 非公平锁允许新来的线程插队,这可能会导致某些线程长时间等待。
热门推荐
微信呼叫"对方忙线中"?六种可能原因解析
越鞠丸助你告别坏情绪
朱丹溪亲传:越鞠丸调理秘籍
《丹溪心法》揭秘越鞠丸:从六郁理论到现代应用
越鞠丸:调理气郁,改善消化不适的中医良方
“勇士”与东方红:军用越野卡车技术大比拼
德国牧羊犬:军犬界的全能战士
《刘老根3》:赵本山新作如何反映当代社会现象?
繁昌:千年古迹与现代风采交融之地
赵本山新作登顶,却无缘春晚:一个时代的遗憾
长春最出名的6种美食,每种都是长春人的心头爱,你吃过哪几种?
大年初三“谷子生日”,讲究:忌1样,吃3样,寓意衣食无忧好年景
大年初二——回娘家
秋冬团建好去处:潮州音乐与潮剧体验
探秘潮州古城:镇海楼与象埔寨的历史密码
《中国国家地理》认证:潮州最美拍照点全攻略
法人股东的股东会决议如何做记录
东方明珠塔自驾游全攻略:停车、门票、游览路线详解
初夏打卡!上海&江苏最美自然景观推荐
成都人的早饭,绝对不将就,这18家早餐店,一定要打卡
上海地铁公交最新支付指南:刷手机轻松出行!
上海下周出行攻略:晴雨交替,如何玩转这座魔都?
百色绝美打卡点:通灵大峡谷&鹅泉风景区
凌云茶山金字塔:深秋探秘百色历史文化的绿色奇迹
冬游百色:避寒康养必打卡景点推荐
百色起义纪念馆:缅怀革命先烈,传承红色精神
王者荣耀:诸葛亮最新出装攻略及实战技巧详解
王者荣耀诸葛亮最强出装攻略:三套主流方案详解与实战应用
王者荣耀诸葛亮最强出装攻略:三种主流方案详解
漳州东山岛旅行指南:细软沙滩、清澈海水与文化之旅