ReentrantLock源码走读分析

首先, ReentrantLock作为一种常用的锁,可以通过构造方法中穿ture来指定是公平锁,还是非公平锁,因此从源码上来分析公平锁和分公平锁有什么区别:

从构造方法可以看出,公平锁非公平锁的区分主要是看ReentrantLock的一个属性类sync的实现来决定的,当公平锁的时候,实现类是FairSync,非公平锁的时候,实现类是NonfairSync

ReentrantLock源码走读分析

ReentrantLock源码走读分析

 

  • NonfairSync的类继承关系
    ReentrantLock源码走读分析

  • FairSync的类继承关系
    ReentrantLock源码走读分析

  • 首先从lock方法进入,可以发现,ReentrantLock的lock方法实现,最终是由sync类来实现的

  • ReentrantLock源码走读分析ReentrantLock源码走读分析

  • 首先我们去看公平锁的lock实现,从代码走读可以看出,公平锁首先会调用尝试获取锁的方法,当获取锁失败,并且等待队列满了的情况下,当前线程便会被中断

  • ReentrantLock源码走读分析

  • 其中我们可以发现,acquire方法是AbstractQueuedSynchronizer类的,也就是AQS,所以lock的底层是由AQS实现的

  • ReentrantLock源码走读分析

我们再来看公平锁的tryAcquire()方法实现,走读代码,首先会获取当前线程,然后获取AQS中的status,也就是锁的状态,当status为0时,锁未被占有,通过cas(compareAndSetState,其底层实现是由unsafe类实现的,最终native修饰,即c语言编写,最终通过cup原语支持,以及内存一致性协议),将锁的拥有者设置为当前线程,从而完成了加锁的功能;如果当前锁状态是被占有的,则判断占有锁的线程是不是当前线程,如果是当前线程,则status再加1,从而达到ReentrantLock可重入的目的

  •  

    hasQueuedPredecessors()方法是区别公平锁与非公平锁最主要的方法,其中主要是判断等待队列中是否有线程等待获取锁,以及当前线程是否排在队列第一位,如果不是,则不会尝试加锁

     

  • ReentrantLock源码走读分析

  • status是通过volatile修饰的,可以保证线程之间的可见性,保证了多线程情况下的锁竞争

  • ReentrantLock源码走读分析

  • 如果尝试获取锁失败的话,则会调用acquireQueued方法放入一个等待队列中,队列的实现原理是一个volatile修饰的Node类,也就是一个双向列表,将当前线程加在链表的最后一位

  • 再来看非公平锁的实现方式,其中实现方式大致相同,主要区别在于没有判断hasQueuedPredecessors()方法的返回值,也就是当前线程不管是不是队列中的第一个,或者队列为空,都直接去获取锁

  • ReentrantLock源码走读分析

  • ReentrantLock源码走读分析