本文主要是介绍ReentrantLock底层实现 小结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1. FairSync 的 state & tail & head
tail:尾节点, 链表
head:头节点, 链表
state:锁状态
简单来说
lock()
1). 看看state状态,合适就拿着state直接开跑
2). 不合适就在把自己放在head链表最后
3). 首先找到自己前一个状态合格的哥们,如果前面哥们的状态是CANCELLED,那需要把这哥们从head链表中剔除掉,然后知道依次向前找到一个状态合格的哥们
4). 把找到的哥们状态置为SIGNAL,然后自己就去安心睡觉(LockSupport.park)
(最前排的哥们叫”哨兵节点“,“哑节点”)
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; // help GCfailed = false;return interrupted;}if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())interrupted = true;}} finally {if (failed)cancelAcquire(node);}}
unlock()
1). 把 state-1看看,如果>0那不好意思哥们我仍然持有当前锁,如果==0那么就把 state=0
2). 然后检查链表里的头个Node状态是非CANCELLED时,则把头节点后面的兄弟拿出来叫醒(LockSupport.unpark)
lockInterruptibly()
1). 当前线程处于LockSupport.park时,可以被interrept和unlock唤醒。lockInterruptibly()处理interrept是及时throw new InterruptedException(),而lock()只是标记一下,直到拿到锁才会Thread.currentThread().interrupt()
2. Condition firstWaiter & lastWaiter(只有持有锁的线程才有资格await(), signal()。否则抛出java.lang.IllegalMonitorStateException)
await()
1). 创建当前线程对应的Node并放入firstWaiter
2). 把当前线程持有的Lock全部释放(<=>特殊的unlock)
3). 然后从FairSync 的的链表中找出第二个节点进行LockSupport.unpark
4). 停下自己,LockSupport.park(this)
public final void await() throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();Node node = addConditionWaiter();int savedState = fullyRelease(node);int interruptMode = 0;while (!isOnSyncQueue(node)) {LockSupport.park(this);if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)break;}if (acquireQueued(node, savedState) && interruptMode != THROW_IE)interruptMode = REINTERRUPT;if (node.nextWaiter != null) // clean up if cancelledunlinkCancelledWaiters();if (interruptMode != 0)reportInterruptAfterWait(interruptMode);}
signal()
1) 从 firstWaiter链表中拿出第一个然后放到 head链表最后
这篇关于ReentrantLock底层实现 小结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!