ReentrantLock意思為可重入鎖,指的是一個(gè)線程能夠?qū)σ粋€(gè)臨界資源重復(fù)加鎖。
借用美團(tuán)技術(shù)博客的一張圖說(shuō)明它和Synchronized的區(qū)別


????ReentrantLock沒(méi)有直接繼承AbstractQueuedSynchronizer,而是Sync繼承的。Sync又是個(gè)抽象類,有NonfairSync和FairSync兩個(gè)子類??梢钥吹侥J(rèn)的構(gòu)造函數(shù)是非公平鎖,另一個(gè)構(gòu)造函數(shù)則指定公平/非公平。
????全局變量sync在構(gòu)造函數(shù)里被賦值,在加鎖、解鎖等操作的時(shí)候使用sync里面的API
在開(kāi)始之前要知道公平鎖和非公平鎖的區(qū)別
????公平鎖:多個(gè)線程按照申請(qǐng)鎖的順序去獲得鎖,線程會(huì)直接進(jìn)入隊(duì)列去排隊(duì),永遠(yuǎn)都是隊(duì)列的第一位才能得到鎖。
????優(yōu)點(diǎn):所有的線程都能得到資源,不會(huì)餓死在隊(duì)列中。
????缺點(diǎn):吞吐量會(huì)下降很多,隊(duì)列里面除了第一個(gè)線程,其他的線程都會(huì)阻塞,cpu喚醒阻塞線程的開(kāi)銷會(huì)很大
????非公平:多個(gè)線程去獲取鎖的時(shí)候,會(huì)直接去嘗試獲取,獲取不到,再去進(jìn)入等待隊(duì)列,如果能獲取到,就直接獲取到鎖。
????優(yōu)點(diǎn):可以減少CPU喚醒線程的開(kāi)銷,整體的吞吐效率會(huì)高點(diǎn),CPU也不必取喚醒所有線程,會(huì)減少喚起線程的數(shù)量。
????缺點(diǎn):可能會(huì)導(dǎo)致隊(duì)列中間的線程一直獲取不到鎖或者長(zhǎng)時(shí)間獲取不到鎖,導(dǎo)致餓死。
加鎖API
public void lock() {
sync.lock();
}
FairSync實(shí)現(xiàn)
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
// 調(diào)用AQS的acquire,AQS的acquire又會(huì)調(diào)用子類的tryAcquire
acquire(1);
}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 獲取AQS的同步狀態(tài),如果鎖沒(méi)有被占用(0沒(méi)占用,1占用),那么獲取鎖
if (c == 0) {
// 如果沒(méi)有其他線程比當(dāng)前線程等待的時(shí)間更長(zhǎng),那么就把AQS的同步狀態(tài)置為1
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
// 設(shè)置同步狀態(tài)成功后,把當(dāng)前線程設(shè)置為獨(dú)占線程,獲取鎖成功
setExclusiveOwnerThread(current);
return true;
}
}
// 鎖被占用,并且是自己占用的話,就加重入次數(shù),否則,獲取鎖失敗返回false
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
NonfairSync實(shí)現(xiàn)
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))
setExclusiveOwnerThread(Thread.currentThread());
else // 如果CAS更新同步狀態(tài)失敗再去acquire,acquire又會(huì)調(diào)用tryAcquire
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 鎖沒(méi)沒(méi)有被占用則獲取鎖
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 獲取鎖的是自己則累加重入次數(shù)
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;
}
響應(yīng)中斷獲取鎖
public void lockInterruptibly() throws InterruptedException {
// 調(diào)用AQS的acquireInterruptibly,如果當(dāng)前線程沒(méi)有被中斷則獲取鎖
sync.acquireInterruptibly(1);
}
有返回值的獲取鎖
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 沒(méi)有其他線程獲取鎖,則將當(dāng)前線程設(shè)置為獨(dú)享線程,返回true
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 當(dāng)前線程已經(jīng)擁有鎖了,重入
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
// state設(shè)置為重入的層數(shù)
setState(nextc);
return true;
}
// 沒(méi)拿到鎖返回false
return false;
}
}
釋放鎖API
釋放鎖是不分公平和非公平的,release是AQS的方法,不允許子類重寫。但是其中的tryRelease強(qiáng)制子類重寫
public void unlock() {
sync.release(1);
}
public final boolean release(int arg) {
// 釋放鎖
if (tryRelease(arg)) {
// 如果還有頭節(jié)點(diǎn),并且頭節(jié)點(diǎn)的waitStatus不是初始值,則喚醒后繼節(jié)點(diǎn)的線程
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
// 當(dāng)前state-releases=還剩下的重入層數(shù)
int c = getState() - releases;
// 如果不是當(dāng)前線程獨(dú)占,那么不允許當(dāng)前線程釋放鎖
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 如果重入層數(shù)是0了,那么就代表當(dāng)前線程沒(méi)鎖了,free=true
if (c == 0) {
free = true;
// 清空獨(dú)占線程
setExclusiveOwnerThread(null);
}
// 設(shè)置state,不管state是0還是非0
setState(c);
// 返回free
return free;
}