## ReenTrantLock是什么
ReenTrantLock是juc包下的一個經(jīng)典的互斥鎖,也是 **可重入鎖**(即當前線程在已經(jīng)獲取改鎖后重復(fù)執(zhí)行獲取鎖操作時不會引起死鎖,并且不需要執(zhí)行獲取鎖的操作),ReenTrantLock是基于AQS來實現(xiàn)的(PS:注意是基于不是繼承,看到網(wǎng)上有的同學會說發(fā)現(xiàn)ReentrantLock并沒有繼承AQS有所疑問),如果有對AQS不了解的同學可以查看我之前的文章[淺析AQS(1)---獨占鎖以及共享鎖的實現(xiàn)](http://blog.xiaoazhai.com/aqs/)以及[淺析AQS (二)--condition的實現(xiàn)](http://blog.xiaoazhai.com/aqs2/),
<!--more-->
首先ReenTrantLock是默認的非公平鎖,但是也有公平鎖的實現(xiàn),需要在構(gòu)造方法中傳入是否公平的Boolean值來標志,需要注意的是,此處的公平與非公平只針對lock方法,而tryLock方法是指定非公平的.并不受限制
ReenTrantLock實現(xiàn)并發(fā)控制是依靠內(nèi)部類Sync及其兩個子類FairSync和NoFairSync,顧名思義這兩個子類是提供公平鎖以及非公平鎖的實現(xiàn),而Sync則是繼承了AQS的具體實現(xiàn)類,接下來我們結(jié)合源碼具體分析
## Sync內(nèi)部類
首先查看一下Sync的源碼
```java
? ? abstract static class Sync extends AbstractQueuedSynchronizer {
? ? ? ? private static final long serialVersionUID = -5179523762034025860L;
? ? ????//抽象lock方法 根據(jù)公平與非公平實現(xiàn)執(zhí)行不同的操作
? ? ? ? abstract void lock();
????????//非公平嘗試獲取鎖
? ? ? ? final boolean nonfairTryAcquire(int acquires) {
? ? ? ? ? ? final Thread current = Thread.currentThread();
? ? ? ? ? ? int c = getState();
? ? ? ? ? ? if (c == 0) {
? ? ? ? ? ? ? ? //如果當前鎖沒有被人獲取過則直接嘗試獲取鎖
? ? ? ? ? ? ? ? if (compareAndSetState(0, acquires)) {
? ? ? ? ? ? ? ? ? ? //設(shè)置當前持有鎖的線程
? ? ? ? ? ? ? ? ? ? setExclusiveOwnerThread(current);
? ? ? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? else if (current == getExclusiveOwnerThread()) {
? ? ? ? ? ? ? ? //如果是當前線程獲取了當前鎖則直接重入
? ? ? ? ? ? ? ? int nextc = c + acquires;
? ? ? ? ? ? ? ? if (nextc < 0) // overflow
? ? ? ? ? ? ? ? ? ? throw new Error("Maximum lock count exceeded");
? ? ? ? ? ? ? ? setState(nextc);
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? }
? ? ? ? ? ? return false;
? ? ? ? }
????????//嘗試釋放鎖
? ? ? ? protected final boolean tryRelease(int releases) {
? ? ? ? ? ? int c = getState() - releases;
? ? ? ? ? ? if (Thread.currentThread() != getExclusiveOwnerThread())
? ? ? ? ? ? ? ? throw new IllegalMonitorStateException();
? ? ? ? ? ? boolean free = false;
? ? ? ? ? ? if (c == 0) {
? ? ? ? ? ? ? ? free = true;
? ? ? ? ? ? ? ? setExclusiveOwnerThread(null);
? ? ? ? ? ? }
? ? ? ? ? ? setState(c);
? ? ? ? ? ? return free;
? ? ? ? }
????????// 是否持有當前鎖
? ? ? ? protected final boolean isHeldExclusively() {
? ? ? ? ? ? return getExclusiveOwnerThread() == Thread.currentThread();
? ? ? ? }
????????//新建condition對象
? ? ? ? final ConditionObject newCondition() {
? ? ? ? ? ? return new ConditionObject();
? ? ? ? }
????????//獲取鎖當前的持有線程
? ? ? ? final Thread getOwner() {
? ? ? ? ? ? return getState() == 0 ? null : getExclusiveOwnerThread();
? ? ? ? }
????????//當前線程獲取到了
? ? ? ? final int getHoldCount() {
? ? ? ? ? ? return isHeldExclusively() ? getState() : 0;
? ? ? ? }
? ? ? ? final boolean isLocked() {
? ? ? ? ? ? return getState() != 0;
? ? ? ? }
? ? }
```
在Sync對象中,重寫了tryRelease方法,將釋放鎖的邏輯統(tǒng)一,并且定義了nonfairTryAcquire非公平獲取鎖的方法,這里為什么要將該方法定義在父類是因為無論是公平還是非公平鎖,tryLock方法中都是采用非公平獲取的方式,而無論維護的Sync對象時公平的還是非公平的,我們都需要一個可以非公平獲取鎖的方式
在nonfairTryAcquire我們可以看到,如果當前鎖的state為0即當前鎖沒人持有時則采用cas的方式獲取鎖,然后將持有現(xiàn)成設(shè)置為當前線程,而第二個判斷則是可重入鎖的實現(xiàn),即判斷持有鎖的是不是當前線程,如果是則直接獲取鎖
關(guān)于ConditionObject的實現(xiàn)可以查看我以前的文章[淺析AQS (二)--condition的實現(xiàn)](http://blog.xiaoazhai.com/aqs2/),
## FairSync與NoFairSync
下面放一下公平與非公平鎖的具體實現(xiàn)
```java
static final class NonfairSync extends Sync {
? ? ? ? private static final long serialVersionUID = 7316153563782823691L;
? ? ? ? final void lock() {
? ? ? ? ? ? //嘗試獲取鎖
? ? ? ? ? ? if (compareAndSetState(0, 1))
? ? ? ? ? ? ? ? setExclusiveOwnerThread(Thread.currentThread());
? ? ? ? ? ? else
? ? ? ? ? ? ? ? acquire(1);
? ? ? ? }
? ? ? ? protected final boolean tryAcquire(int acquires) {
? ? ? ? ? ? return nonfairTryAcquire(acquires);
? ? ? ? }
? ? }
? ? static final class FairSync extends Sync {
? ? ? ? private static final long serialVersionUID = -3000897897090466540L;
? ? ? ? final void lock() {
? ? ? ? ? ? acquire(1);
? ? ? ? }
? ? ? ? protected final boolean tryAcquire(int acquires) {
? ? ? ? ? ? final Thread current = Thread.currentThread();
? ? ? ? ? ? int c = getState();
? ? ? ? ? ? if (c == 0) {
? ? ? ? ? ? ? ? //判斷是否有在隊列中阻塞的線程,或者當前線程是否為隊列的頭
? ? ? ? ? ? ? ? if (!hasQueuedPredecessors() &&
? ? ? ? ? ? ? ? ? ? compareAndSetState(0, acquires)) {
? ? ? ? ? ? ? ? ? ? setExclusiveOwnerThread(current);
? ? ? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? else if (current == getExclusiveOwnerThread()) {
? ? ? ? ? ? ? ? int nextc = c + acquires;
? ? ? ? ? ? ? ? if (nextc < 0)
? ? ? ? ? ? ? ? ? ? throw new Error("Maximum lock count exceeded");
? ? ? ? ? ? ? ? setState(nextc);
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? }
? ? ? ? ? ? return false;
? ? ? ? }
```
在NoFairSync中調(diào)用lock方法直接嘗試用cas的方式獲取鎖,并不去查看你是否有鎖占用,直接嘗試獲取,如果成功則直接獲取鎖,如果失敗則采用acquire的方式來獲取
而在FairSync中實現(xiàn)的tryAcquire方法中與Sync類中的noFairTryAcquire基本一致,只是在沒人獲取鎖時判斷當前隊列是否為空,或者當前線程是否在隊列的最開始位置,總得來說就是判斷是否有其他線程等待時長比當前線程要長,主要是為了保證獲取鎖的公平性
## ReenTrantLock
接下來我們看看ReenTrantLock是如何使用這兩種鎖的,首先來看看構(gòu)造方法
```java
? public ReentrantLock() {
? ? ? ? sync = new NonfairSync();
? ? }
? ? public ReentrantLock(boolean fair) {
? ? ? ? sync = fair ? new FairSync() : new NonfairSync();
? ? }
```
這里指定了鎖的公平與非公平,默認采用非公平鎖,如需公平鎖則傳入一個true即可
接下來查看lock與tryLock方法
```java
? ? public void lock() {
? ? ? ? sync.lock();
? ? }
? ? public boolean tryLock() {
? ? ? ? return sync.nonfairTryAcquire(1);
? ? }
```
如同上文所說,在lock方法中是根據(jù)當前所公平與非公平來進行而tryLock方法則是固定以非公平的方式來進行調(diào)用
以上就是ReenTrantLock的具體實現(xiàn)方式,結(jié)合AQS的兩篇文章即可將該類理解通透
![我的公眾號](https://image-xiaoazhai.oss-cn-hangzhou.aliyuncs.com/blog/qrcode_for_gh_d6d50bf01095_430.jpg)