ReentrantLock
ReentrantLock是一個互斥鎖,也是一個可重入鎖。ReentrantLock鎖在同一時刻只能被一個線程持有,但是它可被單個線程多次獲取,每獲取一次AQS的state就加1。
ReentrantLock內部的實現(公平鎖和非公平鎖)都是基於內部Sync的實現。
內部結構
ReentrantLock內部定義了三個重要的內部類,Sync、FairSync、NonfairSync。
Sync繼承自抽象類AbstractQueuedSynchronizer,FairSync(公平鎖)和 NonfairSync(非公平鎖)繼承於Sync。
Sync
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
abstract void lock();
//非公平鎖的TryAcquire
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {//沒有被任何線程持有
if (compareAndSetState(0, acquires)) {//CAS 獲取
setExclusiveOwnerThread(current);//獲取成功,將當前線程設置爲Owner
return true;
}
}
else if (current == getExclusiveOwnerThread()) {//如果當前線程已獲取鎖,將state+1返回
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();
}
//newCondition
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;
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
Sync是ReentrantLock實現同步控制的基礎。Sync內部定義了一些方法:lock(獲取鎖的方法,在子類實現)、nonfairTryAcquire(非公平鎖的嘗試獲取資源)、tryRelease(釋放資源)。
NonfairSync
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);
}
}
NonfairSync是內部非公平鎖的定義,非公平鎖獲取鎖的流程:
- 調用lock方法,lock方法首先會進行CAS操作,將state屬性嘗試設置爲1,如果成功,則代表獲取到鎖,將exclusiveOwnerThread屬性設置爲當前獲取鎖的線程。
- 如果線程CAS失敗,則調用AQS的acquire方法,去獲取鎖,tryAcquire(1)是子類自己的實現,調用了nonfairTryAcquire方法。如果調用了nonfairTryAcquire方法獲取鎖失敗,那就會吧當前線程包裝爲Node加入同步隊列。
FairSync
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
//tryAcquire方法的公平鎖版本,雖然是公平的,但是不保證一定會獲取鎖,除非是遞歸調用或者是第一個節點或者是前面無等待線程
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
//hasQueuedPredecessors方法判斷當先線程前面是否還有等待線程,如果有等待線程,則不去競爭獲取鎖
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;
}
}
公平鎖在加鎖的時候不會先嚐試去加鎖,直接去調用AQS的acquire方法去獲取鎖,在自己定義的嘗試獲取資源中,如果state爲0,也會先去判斷當前線程前面是否還有線程等待,如果沒有等待的線程纔會自己獲取鎖,否則加入等待隊列;如果是當前線程獲取到了鎖則state+1.
公平鎖和非公平鎖的不同
- 公平鎖能保證:老的線程排隊使用鎖,新線程仍然排隊使用鎖。
- 非公平鎖保證:老的線程排隊使用鎖;但是無法保證新線程搶佔已經在排隊的線程的鎖。