AQS 自定义同步锁,挺难的! (4)

根据现在等待队列中的节点状态,p == head是返回true的,然后就是tryAcquire(arg)了,由于线程A已经释放了锁,那现在的线程B自然就能获取到锁了,所以tryAcquire(arg)也会返回true。

设置队列头

线路B拿到锁后,会调用setHead(node)自己设置为队列的头:

private void setHead(Node node) { head = node; node.thread = null; node.prev = null; }

调用setHead(node)后队列会发生些变化 :

AQS 自定义同步锁,挺难的!

移除上一个节点

setHead(node)执行完后,接着按上一个节点完全移除:

p.next = null;

此时的队列:

AQS 自定义同步锁,挺难的!

线程B 释放锁

线程B 释放锁的流程与线程A基本一致,只是当前队列中已经没有需要唤醒的线程,所以不需要执行代码去唤醒其他线程:

if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; }

h != null && h.waitStatus != 0这里的h.waitStatus已经是0了,不满足条件,不会去唤醒其他线程。

总结

文中通过自定义一个CustomLock类,然后通过查看AQS源码来学习AQS的部分原理。通过完整的走完锁的获取、释放两个流程,加深对AQS的理解,希望对大家有所帮助。

欢迎关注我的公众号:架构文摘,获得独家整理120G的免费学习资源助力你的架构师学习之路!

公众号后台回复arch028获取资料:

AQS 自定义同步锁,挺难的!

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygwzg.html