圖1-1java
根據上圖能夠知道,ReenTrantLock繼承了Lock接口,Lock接口聲明方法以下:bash
方法名 | 說明 | 拋出異常 |
---|---|---|
lock() | 一直阻塞獲取鎖,直到獲取成功 | 無 |
lockInterruptibly() | 嘗試獲取鎖,直到獲取鎖或者線程被中斷 | InterruptedException |
tryLock() | 嘗試獲取空閒的鎖,獲取成功返回true,獲取失敗返回false,不會阻塞,當即返回 | 無 |
tryLock(long time, TimeUnit unit) | 嘗試在time時間內獲取空閒的鎖,在等待時間內能夠被中斷 | InterruptedException |
unlock() | 釋放鎖 | 無 |
newCondition() | 返回當前鎖的一個condition實例,用於條件性等待 | 無 |
1.ReentrantLock的部分方法ui
圖2-1spa
Sync是NonfairSync 和FairSync 的父類,聲明方法以下:線程
/**
* 抽象方法,獲取鎖
*/
abstract void lock();
/**
* 實現非公平鎖獲取邏輯
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState(); //父類同步器方法,獲取當前同步狀態,後續文章會分析
if (c == 0) {//狀態等於0表示沒有獲取到鎖
if (compareAndSetState(0, acquires)) { //CAS方式修改狀態
setExclusiveOwnerThread(current); //修改爲功後設置當前線程爲鎖的全部者
return true;
}
}
else if (current == getExclusiveOwnerThread()) {//當前鎖已被佔用,判斷是否是本身獲取到了鎖,鎖重入
int nextc = c + acquires; //獲取鎖的計數器
if (nextc < 0) // overflow //由於是int類型,若是超過int最大值會溢出爲負
throw new Error("Maximum lock count exceeded");
setState(nextc);//設置計數器爲狀態值
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
int c = getState() - releases;//釋放鎖,同步狀態減int值
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException(); //若是當前相差不是鎖的擁有者,拋出異常
boolean free = false;
if (c == 0) { //若是同步狀態值爲0,表示鎖已經釋放成功
free = true;
setExclusiveOwnerThread(null); // 設置鎖的擁有線程爲null
}
setState(c);//從新賦值同步狀態
return free;
}
//判斷當前線程是否是鎖獨佔
protected final boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
//返回鎖的ConditionObject實例
final ConditionObject newCondition() {
return new ConditionObject();
}
// Methods relayed from outer class
//獲取當前佔有鎖的線程
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
//獲取當前鎖計數
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
//判斷是否獲取到鎖
final boolean isLocked() {
return getState() != 0; //能夠知道判斷獲取鎖的關鍵就是是否不等於0
}
複製代碼
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))//CAS獲取鎖
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
複製代碼
lock()
和tryAcquire(int acquires)
方法,其中和tryAcquire(int acquires)
方法直接調用了父類的nonfairTryAcquire(acquires)
,介紹父類的時候已經解析過,不清楚能夠看上文Sync解析部分。根據lock源碼發現,開始判斷是不是第一次獲取鎖,若是獲取鎖成功,就把當前線程設置爲鎖的佔有者,不然調用父類的acquire(1)
方法(下一篇介紹同步器會介紹)。static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
/**調用父類的acquire()方法*/
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;
}
}
複製代碼
!hasQueuedPredecessors()
判斷,其實該方法就是判斷是否有比當前線程等待最長時間的線程,若是沒有,那麼就嘗試獲取鎖,獲取成功後設置當前線程爲鎖的佔有者,因此,公平與不公平就是是否按照時間等待來獲取鎖的,好比食堂吃飯,排隊一個個來,這就是公平,若是有人插隊,這就是不公平。public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
public void lock() {
sync.lock();
}
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
//指定超時時間內獲取鎖,阻塞時間爲timeout
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
public Condition newCondition() {
return sync.newCondition();
}
public int getHoldCount() {
return sync.getHoldCount();
}
public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
}
public final boolean isFair() {
return sync instanceof FairSync;
}
protected Thread getOwner() {
return sync.getOwner();
}
public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
public final boolean hasQueuedThread(Thread thread) {
return sync.isQueued(thread);
}
public final int getQueueLength() {
return sync.getQueueLength();
}
protected Collection<Thread> getQueuedThreads() {
return sync.getQueuedThreads();
}
public boolean hasWaiters(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
}
public int getWaitQueueLength(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
}
protected Collection<Thread> getWaitingThreads(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
}
複製代碼
sync
,在介紹sync
時候已經說過,它就是繼承了AbstractQueuedSynchronizer
同步器,不少方法都是直接調用父類同步器的方法,下一篇《java鎖之ReentrantLock(二)》會重點解析AbstractQueuedSynchronizer
同步器源碼,分析同步器是如何依託於FIFO隊列完成鎖的機制。