ReentrantLock 简介

ReentrantLock 是 java.util.concurrent.locks 中的一个可重入锁类。在高竞争条件下有更好的性能,且可以中断。ReentrantLock 是基于 AQS 实现的。AQS 是基于 FIFO 队列的实现,整个 AQS 是典型的模板模式的应用,设计的十分精巧,对于 FIFO 队列的各种操作在 AQS 中就已经实现了,AQS 的子类一般只需要重写 tryAcquire(int arg) 和 tryRelease(int arg) 两个方法即可。

ReentrantLock 中有一个抽象类 Sync 继承自 AbstractQueuedSynchronizer。ReentrantLock 根据传入构造方法的布尔型参数实例化出 Sync 的实现类 FairSync 和 NonFairSync,分别表示公平的 Sync 和非公平的 Sync,FairSync 和 nonFairSync 都是 ReentrantLock 的静态内部类。Sync 是一个抽象类,而 fairSync 和 nonFairSync 则是具体类,分别对应了公平锁和非公平锁。由于 Reentrant 我们用的比较多的是非公平锁,所以看下非公平锁是如何实现的。假设线程 1 调用了 ReentrantLock 的 lock() 方法,那么线程 1 将会独占锁,整个调用链十分简单

第一个获取锁的线程就做了两件事:

  1. 设置 AbstractQueuedSynchronizer 的 state 为 1(同步状态,0 表示未锁)

  2. 设置 AbstractOwnableSynchronizer 的 thread 为当前线程(这个是 AQS 父类 AbstractOwnableSynchronizer 的属性,表示独占模式同步器的当前拥有者)

1
2
3
4
5
6
final void lock(){
if(compareAndSetState(0,1))
setExclusiveownerThread(Thread.currentThread());
else
acquire(1);
}
  1. 当第二个线程想要获取锁时,会先进行 CAS,判断 state 是否为0,如果是则将其设为 1,并返回 true,否则返回 false。由于第一个线程还没有会执行完,所以当然会返回 false,故第二个线程会执行 else 语句块,调用 acquire() 方法,进而调用 acquire 中的 tryacquire 方法,如果 tryacquire 返回 false,则将其加入等待队列。

参考文章:

  1. https://www.cnblogs.com/gxyandwmm/p/9387833.html

  2. https://www.tuicool.com/articles/R7Fnaa

-----------本文结束感谢您的阅读-----------
0%