您好,登錄后才能下訂單哦!
ArrayList源碼分析--jdk1.8
LinkedList源碼分析--jdk1.8
HashMap源碼分析--jdk1.8
AQS源碼分析--jdk1.8
ReentrantLock源碼分析--jdk1.8
??1. ReentrantLock是獨(dú)占鎖。
??2. ReentrantLock分為公平模式和非公平模式。
??3. ReentrantLock鎖可重入(重新插入)
/**
* @since 1.5
* @author Doug Lea
* 獨(dú)占鎖 --默認(rèn)使用非公平鎖模式
* 可重入
*
* synchronized鎖通過監(jiān)視器Monitor來實(shí)現(xiàn)同步,monitorenter加鎖,monitorexit解鎖。
* synchronized是可重如的非公平鎖
* synchronized在jdk1.6進(jìn)行優(yōu)化,添加了偏向鎖、輕量級鎖、重量級鎖,關(guān)鍵字之鎖的升級(偏向鎖->輕量級鎖->重量級鎖)
* 偏向鎖:當(dāng)線程訪問同步塊時,會使用 CAS 將線程 ID 更新到鎖對象的 Mark Word 中,如果更新成功則獲得偏向鎖,并且之后每次進(jìn)入這個對象鎖相關(guān)的同步塊時都不需要再次獲取鎖了。
* 輕量級鎖:如果同步對象為無鎖狀態(tài)時,直接嘗試CAS更新Mark Word添加鎖,如果成功,獲得鎖,失敗升級為重量級鎖
* 重量級鎖:是指當(dāng)鎖是輕量級鎖時,當(dāng)自旋的線程自旋了一定的次數(shù)后,還沒有獲取到鎖,就會進(jìn)入阻塞狀態(tài),該鎖升級為重量級鎖,重量級鎖會使其他線程阻塞,性能降低。
* 在使用 CAS 時,如果操作失敗,CAS 會自旋再次嘗試。由于自旋是需要消耗 CPU 資源的,所以如果長期自旋就白白浪費(fèi)了 CPU。JDK1.6加入了適應(yīng)性自旋:如果某個鎖自旋很少成功獲得,那么下一次就會減少自旋。
*/
public class ReentrantLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L;
private final Sync sync;
/**
* Sync內(nèi)部類,繼承AQS,實(shí)現(xiàn)獨(dú)占鎖模式,作為基礎(chǔ)內(nèi)部類
*/
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* 加鎖
*/
abstract void lock();
/**
* 判斷 reentranLock 狀態(tài) 是否被鎖?。╯tate ?= 0)
* <p>如果沒被鎖住嘗試 原子性上鎖 失敗返回false</>
* <p>如果被鎖住 判斷是否是當(dāng)前線程持有鎖(重入鎖的實(shí)現(xiàn)) 如果是 state + 1
* (信號量 記錄該線程持有鎖的次數(shù)。 該線程每次釋放所 信號量 -1。 信號量為零 代表 鎖被真正釋放)</>
* <p>else 返回false</p>
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread(); //獲取到當(dāng)前的線程
int c = getState(); //獲取鎖的狀態(tài)
if (c == 0) { //目前沒有人在占有鎖 如果鎖已被經(jīng)釋放 再次嘗試獲取鎖
if (compareAndSetState(0, acquires)) { //直接嘗試把當(dāng)前只設(shè)置成1,如果成功,把owner設(shè)置自己,并且退出
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) { // 如果當(dāng)前線程為鎖的擁有者
int nextc = c + acquires; //這里就是重入鎖的概念,如果還是自己,則進(jìn)行加1操作,因?yàn)獒尫藕瞳@取一定要是對等的
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc); // 累加 state 的值 此段代碼 實(shí)現(xiàn)了重入鎖
return true;
}
return false; //當(dāng)前鎖被其他線程占用,退出。
}
/**
* 釋放鎖,默認(rèn)releases傳1
*/
protected final boolean tryRelease(int releases) {
int c = getState() - releases; //獲取當(dāng)前的鎖的狀態(tài)并且減1,因?yàn)橐尫沛i
if (Thread.currentThread() != getExclusiveOwnerThread()) //如果當(dāng)前自己不是鎖的持有者,只有自己才能釋放鎖
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) { //釋放成功
free = true;
setExclusiveOwnerThread(null);
}
setState(c); //重新設(shè)置成狀態(tài)
return free;
}
/**
* 如果當(dāng)前線程獨(dú)占著鎖,返回true
*/
protected final boolean isHeldExclusively() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
}
/**
* 條件隊(duì)列
*/
final ConditionObject newCondition() {
return new ConditionObject();
}
/**
* 返回鎖的擁有者的線程
* 當(dāng)前狀態(tài)為0返回null,說明在等待中
* 當(dāng)前狀態(tài)不為0返回當(dāng)前線程
*/
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
/**
* 當(dāng)前線程占著鎖返回 state,否則返回0
*/
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
/**
* state狀態(tài)不為0標(biāo)識上鎖,為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
}
}
/**
* 構(gòu)造方法,默認(rèn)選擇非公平鎖
*/
public ReentrantLock() {
sync = new NonfairSync();
}
/**
* 構(gòu)造方法,true公平鎖,false非公平鎖
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
?? ReentrantLock implements Lock
?? Sync extends AbstractQueuedSynchronizer
?? 1.ReentrantLock實(shí)現(xiàn)Lock接口,Lock接口定義了加鎖、條件隊(duì)列、解鎖、加鎖(中斷異常)
?? 2.Sync繼承AQS抽象類,實(shí)現(xiàn)了獨(dú)占鎖,作為基礎(chǔ)內(nèi)部類ReentrantLock源碼分析
1. FairSync公平鎖--內(nèi)部類
/**
* 公平鎖
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
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();
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;
}
}
/**
* 非公平鎖的同步對象
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
* 非公平鎖,每次先去獲取對象,所以不排隊(duì),不公平
*/
final void lock() {
// 通過原子操作 改變上鎖狀態(tài)
if (compareAndSetState(0, 1)) // 變更成功,說明獲取鎖成功
setExclusiveOwnerThread(Thread.currentThread()); // 設(shè)置持有者為當(dāng)前線程
else //變更失敗
acquire(1); //嘗試以獨(dú)占模式獲取鎖,如果失敗加入node節(jié)點(diǎn)到隊(duì)列中
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
/**
* 是否有等待線程
*/
public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
/**
* 是否有等待線程
*/
public final boolean hasQueuedThreads() {
return head != tail;
}
1)ReentrantLock是可重入的公平/非公平模式的獨(dú)占鎖。
2)ReentrantLock公平鎖往往沒有非公平鎖的效率高,但是,并不是任何場景都是以TPS作為唯一指標(biāo),公平鎖
能夠減少“饑餓”發(fā)生的概率,等待越久的請求越能夠得到優(yōu)先滿足。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。