代码改变世界

ReentrantLock源码

2022-12-06 21:13  杭伟  阅读(18)  评论(0编辑  收藏  举报

ReentrantLock即是AQS线程同步队列器思想的具体应用/实现

实现了AQS,并有公平锁和非公平锁(默认非公平锁)两种实现

 

ReentrantLock有三个重要的内部类:Sync(抽象类),NonfaireSync(Sync的非公平锁实现),FairSync(Sync的公平锁实现)

 

Sync抽象类

 

 Sync继承AQS,

 

nonfairTryAcquire()方法

如果State=0,尝试CAS获取锁;

否则,判断当前线程是不是已经拿到锁的线程(可重入=一个线程获取了锁再次尝试获取锁时不会出现死锁)

并累加State来记录重入次数。

*小细节:因为State是从0开始的累加值,为什么会判断nextc<0? 因为int为16位最大值为2147483647(允许重入的最大次数),超出即溢出为负数。

 

tryRelease()方法

实现的AQS的tryRelease

 返回值代表的是:是否完全被释放。

 

NonfaireSync(非公平锁)实现类

NonfairSync继承Sync

lock()方法

 非公平锁的lock方法,可以看到,上来就给一次机会,通过CAS设置全局状态值为1,设置成功即抢到锁。

这个机会抢不到,则使用AQS的acquire()方法去排队。

而公平锁那边的实现:直接去排队。

 

tryAcquire()方法 【override】

非公平锁中acquire()会调用tryAcquire()

 tryAcquire()调用nonfairTryAcquire()

在这里可以看到,非公平锁进行了2次CAS操作来尝试获取锁。若2次都失败,则去排队。

细节:为什么nonfairTryAcquire()方法会被定义在Sync抽象类(而不是非公平锁的实现类)中?

 

FairSync(公平锁)实现类

FairSync继承Sync

lock()方法

直接调用AQS的acquire()方法排队

 

 AQS中acquire方法会调用tryAcquire方法。

tryAcquire()方法 【override】

如果锁空闲 并且 当前线程之前没有线程(即当前线程在队头,即排队排到我了) ,后面是一个短路与符号&&,则开始CAS获取锁,

后面的逻辑基本与前面的非公平锁一样。

这里保持了FIFO队列的公平特性,排队思想。