非公平锁
因为之前已经分析过AQS,ReentranLock是利用一个实现了AQS的NonfairSync来获取非公平锁。所以只需关注NonfairSync的tryAcquire的实现。
获取锁(nonfairTryAcquire方法定义在Sync内部类中)
获取锁成功分为两种情况,第一个if判断AQS的state是否等于0,表示锁没有人占有。接着,hasQueuedPredecessors判断队列是否有排在前面的线程在等待锁,没有的话调用compareAndSetState使用CAS(Unsafe类调用本地方法)的方式修改state,传入的acquires写死是1。最后线程获取锁成功,setExclusiveOwnerThread将线程记录为独占锁的线程。
第二个if判断当前线程是否为独占锁的线程,因为ReentrantLock是可重入的,线程可以不停地lock来增加state的值,对应地需要unlock来解锁,直到state为零。
释放锁(tryRelease方法定义在Sync内部类中)
通过上面详细的获取锁过程分析,释放锁过程大概可以猜到:头节点是获取锁的线程,先移出队列,再通知后面的节点获取锁。
因为锁是可以重入的,所以每次lock会让state加1,对应地每次unlock要让state减1,直到为0时将独占线程变量设置为空,返回标记是否彻底释放锁。
公平锁的实现
FairSync的源码如下:
与nonfairAcquire()方法相比,唯一的不同之处在于FairSync多了hasQueuedPredecessors()(由AQS提供)方法:
其作用是判断:是否存在比当前线程等待锁时间更长的线程,有就返回true,没有就返回false。 通过判断当前线程在队列中的位置,(比较难理解的是h!=t&&(s=h.next)==null这一条件是代表什么?)
也就是说每次获取锁都需要判断队列中是否还有排在前面的线程,若不存在才能继续获取锁!!,若队列还存在等待线程则获取失败,当前线程进入队列尾部。