死磕 java同步系列之ReentrantLock源码解析(一)——公平锁、非公平锁 (2)

下面我们看一下主要方法的调用关系,可以跟着我的 → 层级在脑海中大概过一遍每个方法的主要代码:

ReentrantLock#lock() ->ReentrantLock.FairSync#lock() // 公平模式获取锁 ->AbstractQueuedSynchronizer#acquire() // AQS的获取锁方法 ->ReentrantLock.FairSync#tryAcquire() // 尝试获取锁 ->AbstractQueuedSynchronizer#addWaiter() // 添加到队列 ->AbstractQueuedSynchronizer#enq() // 入队 ->AbstractQueuedSynchronizer#acquireQueued() // 里面有个for()循环,唤醒后再次尝试获取锁 ->AbstractQueuedSynchronizer#shouldParkAfterFailedAcquire() // 检查是否要阻塞 ->AbstractQueuedSynchronizer#parkAndCheckInterrupt() // 真正阻塞的地方

获取锁的主要过程大致如下:

(1)尝试获取锁,如果获取到了就直接返回了;

(2)尝试获取锁失败,再调用addWaiter()构建新节点并把新节点入队;

(3)然后调用acquireQueued()再次尝试获取锁,如果成功了,直接返回;

(4)如果再次失败,再调用shouldParkAfterFailedAcquire()将节点的等待状态置为等待唤醒(SIGNAL);

(5)调用parkAndCheckInterrupt()阻塞当前线程;

(6)如果被唤醒了,会继续在acquireQueued()的for()循环再次尝试获取锁,如果成功了就返回;

(7)如果不成功,再次阻塞,重复(3)(4)(5)直到成功获取到锁。

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

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