最近面试的时候被问到AQS机制一时忘记了,一怒之下直接把ReentrantLock源码撸了个遍。别问我为啥是ReentrantLock问就是我乐意。
ReentrantLock本身代码肥肠简单,主要依赖Sync这个内部类进行锁操作,所以我们重点来说说Sync类,这个来继承着AbstractQueuedSynchronizer也就是我们这次的主题AQS机制,然后Sync延伸出两个扩展类,一个是NonfairSync(非公平锁:不按请求顺序加锁)和FairSync(公平锁:按请求锁顺序加锁)这两个后面会进行一个对比来讲解,ReentrantLock默认是非公平锁,而且是独占锁。AQS支持两种模式:共享锁以及独占锁。
AQS详解

AbstractQueuedSynchronizer(抽象队列同步器)内部通过定义Head和Tail来指向一个双向链表,然后我们这里来聊聊整个请求锁的逻辑大概如下:
- 请求锁时会先去判断AQS的state是否为0,若是则将state设置成1(默认值),这样就可以占有锁
- 若发现state不为0且线程不是当前线程,则说明锁被其他线程占有,这个时候就会将当前线程包装到一个新的Node追加到链表尾部,然后进入死循环不断尝试获得锁(如操作1),若成功获取到锁,则将当前节点设置为Head。
下图方法介绍:
- tryAcquire :请求锁
- acquireQueued:循环请求锁
- addWaiter:链表尾部添加节点

释放锁过程比较简单,只要将state重置为0,而且将当前获得锁线程置为null即可。
上面线程在不断请求获得锁的时候分两种情况,即为我们上面一开始将的公平锁和非公平锁,下面我们就来说下这两种模式在请求时有什么不同,如下图代码所示,非公平锁与公平锁主体逻辑十分相似,主要不同在于公平锁多了一个非hasQueuedPredecessors逻辑判断。

如下图所示,这个方法我个人觉得如果跟上面的调用放在一起会比较好理解,上面调用是用
!hasQueuedPredecessors,然后我们说的的公平锁是要按照请求顺序来获得,所以这里这个方法的作用肯定就是判断当前请求锁是否为head的下一个节点(next),这样我们再来看下面的逻辑就会比较简单。hasQueuedPredecessors只有在一种情况会返回true,就是head有next节点且不是当前线程。
以上就是AQS核心的一个逻辑,至于共享锁部分逻辑这个后面再写。
