ReentrantLock是一個顯示鎖,實現基礎都是AQS。所謂的AQS就是AbstractQueuedSynchronizer,
AQS的作用
- 用來構建鎖和同步工具的框架, ReentrantLock、CountDownLatch、Semaphore基礎都是AQS
- AQS有個state變量,是int類型,使用了volatile修飾,AQS圍繞state提供兩種基本的獲取和釋放功能
ReentrantLock分析
- 在ReentrantLock中定義了一個抽象的靜態類Sync,該類繼承了AbstractQueuedSynchronizer
- ReentrantLock中還定義了公平鎖和非公平鎖(FairSync/NonfairSync),這兩個鎖繼承了Sync。
- 公平鎖:線程獲取鎖的順序和調用lock的順序一樣,FIFO先進先出
- 非公平鎖:線程鎖獲取所得順序和調用lock的順序無關,隨機的
- ReentrantLock默認是實現非公平鎖
非公平鎖
/**
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/
public ReentrantLock() {
sync = new NonfairSync();
}
也同時提供使用公平鎖了形參構造器方法來
/**
* Creates an instance of {@code ReentrantLock} with the
* given fairness policy.
* @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
- 如何獲取鎖獲取鎖
- ReentrantLock提供lock()方法,該方法直接使用的是Sync類中的lock方法,該方法是個抽象方法,因爲ReentrantLock默認是非公平鎖,所以lock()方法的具體實現在NonfairSync中的lock()中
final void lock() {
//判斷當前state是否是0,如果是0,則將值設爲1,並將當前線程設爲獨佔鎖線程
//否則
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
//如果當前state不是0,則當前線程放入等待隊列
acquire(1);
}
//調用AbstractQueuedSynchronized類中的acquire()來中斷
public final void acquire(int arg) {
//調用NonfairSync非公平鎖類的tryAcquire()方法
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
//使用addWaiter()方法創建一個Node,同時給一個類型
//將線程加入阻塞隊列
//Node.EXCLUSIVE for exclusive, Node.SHARED for shared
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Tail of the wait queue, lazily initialized. Modified only via method enq to add new wait node.
// tail是等待隊列的尾部,延遲初始化,通過enq()方法添加節點
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
//enq方法是一個死循環(是爲了保證Node一定能插入隊列),當隊列爲空時,會創建一個空的Node作爲head節點
enq(node);
return node;
}
//不間斷的獲取已經在隊列中的獨佔線程
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
shouldParkAfterFailedAcquire(Node pred, Node node)該方法的作用是檢查和更新獲取失敗的節點的狀態。如果線程要阻塞就返回true
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
//如果前一個節點的狀態是SIGNAL,阻塞,返回true
return true;
if (ws > 0) {
// 如果前一個節點的狀態是CANCELLED,則跳過所有前置任務(通過循環將前面的節點都移除)
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
//如果是其他狀態,則都將狀態更新爲SIGNAL
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
final boolean nonfairTryAcquire(int acquires) {
//獲取當前線程
final Thread current = Thread.currentThread();
//獲得AQS的state是否等於0,等於0表示沒有人佔有
int c = getState();
if (c == 0) {
// 然後比較並更新state,如果state是0,就把值設爲1
if (compareAndSetState(0, acquires)) {
// 當前線程獲取鎖,並設置線程擁有獨佔訪問權,即獲得獨佔鎖
setExclusiveOwnerThread(current);
return true;
}
}
//判斷當前線程是否是獨佔鎖線程,因爲ReentrantLock是可重入的,線程可以不停的lock來增加state的值,對應的就需要unlock來解鎖,直到state爲0
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;
}
- 鎖的釋放
- ReentrantLock提供了unlock()方法,該方法中調用了Sync中的release方法。sync.release(1);入參寫死爲1,因爲每當一個線程獲取到獨佔線程時,都會把自己設爲head.
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
//喚醒頭節點的下一個節點
unparkSuccessor(h);
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;
}