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。 - 非公平锁允许新来的线程插队,这可能会导致某些线程长时间等待。
热门推荐
冠心病患者,放过支架怎样复查?复查造影的时间点很多人不知道
非遗申请的最佳时机是什么时候?要做哪些准备
頭髮燙壞怎麼辦?髮型師親授嚴重毛躁、斷裂受損髮急救方法,「先潤絲再洗髮」是關鍵
探访桑坡:从UGG到始祖鸟,中国最时尚的村子里人均代购
消防设施维保为什么需要聘请第三方公司?消防公司的设立要求是什么?
【人物篇】隆美尔16:托布鲁克
人工智能驱动的精准医疗:通过个性化干预转型医疗
五年级是把数感练出来的最后一个好机会,一定要把握住
如何走出情绪的牢笼,获得大自在的心态
2024中医药全民阅读大会举行 推动中医药阅读活动提质增效
河南商丘七大特色小吃大揭秘,个个经典美味,你能吃完吗?
硬笔书法教学:腕部挺摆练习详解
小儿脑瘫康复指导
深层解读量子力学,“意识”真的会影响结果吗?(中)
《仙剑世界》终测测评:三十年沉淀而来的浪漫之作
从明朝到清朝,我们与朝鲜的关系有何变化?
「情绪自救指南」| 6个科学方法帮你从emo黑洞全身而退
冰箱温度的设置标准 冰箱温度怎么调节
北青快评|网络主流空间不能被明星八卦“霸榜”
树莓派5安装Home Assistant控制Zigbee开关(有线+无线)
叶黄素酯片的副作用有哪些呢
江浙沪周边自驾游路线汇总表,太有用了!果断珍藏,2025年走起
7座SUV汽车的保养成本究竟高不高
MySQL 关键特性一:插入缓冲、双写缓冲
万恶的旧社会是什么样?看看晚清时期的“童养媳”,处境有多悲惨
碳纤维报价波动大,行业如何应对?
终结11年“无声世界”!复旦团队领衔研究新突破,迎接耳聋基因治疗新时代
美国西点军校在哪个城市 留学专业有些什么
玛卡的食用指南:如何科学健康地享受玛卡的滋补功效
被幼犬咬伤后是否需要接种狂犬病疫苗