新聞中心
JDK1.8
ArrayList源碼分析--jdk1.8
LinkedList源碼分析--jdk1.8
HashMap源碼分析--jdk1.8
AQS源碼分析--jdk1.8
ReentrantLock源碼分析--jdk1.8
10年積累的成都網(wǎng)站建設(shè)、網(wǎng)站制作經(jīng)驗,可以快速應對客戶對網(wǎng)站的新想法和需求。提供各種問題對應的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡服務。我雖然不認識你,你也不認識我。但先網(wǎng)站設(shè)計后付款的網(wǎng)站建設(shè)流程,更有槐蔭免費網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
ReentrantLock概述
??1. ReentrantLock是獨占鎖。
?2. ReentrantLock分為公平模式和非公平模式。
?3. ReentrantLock鎖可重入(重新插入)
ReentrantLock源碼分析
/**
* @since 1.5
* @author Doug Lea
* 獨占鎖 --默認使用非公平鎖模式
* 可重入
*
* synchronized鎖通過監(jiān)視器Monitor來實現(xiàn)同步,monitorenter加鎖,monitorexit解鎖。
* synchronized是可重如的非公平鎖
* synchronized在jdk1.6進行優(yōu)化,添加了偏向鎖、輕量級鎖、重量級鎖,關(guān)鍵字之鎖的升級(偏向鎖->輕量級鎖->重量級鎖)
* 偏向鎖:當線程訪問同步塊時,會使用 CAS 將線程 ID 更新到鎖對象的 Mark Word 中,如果更新成功則獲得偏向鎖,并且之后每次進入這個對象鎖相關(guān)的同步塊時都不需要再次獲取鎖了。
* 輕量級鎖:如果同步對象為無鎖狀態(tài)時,直接嘗試CAS更新Mark Word添加鎖,如果成功,獲得鎖,失敗升級為重量級鎖
* 重量級鎖:是指當鎖是輕量級鎖時,當自旋的線程自旋了一定的次數(shù)后,還沒有獲取到鎖,就會進入阻塞狀態(tài),該鎖升級為重量級鎖,重量級鎖會使其他線程阻塞,性能降低。
* 在使用 CAS 時,如果操作失敗,CAS 會自旋再次嘗試。由于自旋是需要消耗 CPU 資源的,所以如果長期自旋就白白浪費了 CPU。JDK1.6加入了適應性自旋:如果某個鎖自旋很少成功獲得,那么下一次就會減少自旋。
*/
public class ReentrantLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L;
private final Sync sync;
/**
* Sync內(nèi)部類,繼承AQS,實現(xiàn)獨占鎖模式,作為基礎(chǔ)內(nèi)部類
*/
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* 加鎖
*/
abstract void lock();
/**
* 判斷 reentranLock 狀態(tài) 是否被鎖?。╯tate ?= 0)
* 如果沒被鎖住嘗試 原子性上鎖 失敗返回false>
*
如果被鎖住 判斷是否是當前線程持有鎖(重入鎖的實現(xiàn)) 如果是 state + 1
* (信號量 記錄該線程持有鎖的次數(shù)。 該線程每次釋放所 信號量 -1。 信號量為零 代表 鎖被真正釋放)>
*
else 返回false
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread(); //獲取到當前的線程
int c = getState(); //獲取鎖的狀態(tài)
if (c == 0) { //目前沒有人在占有鎖 如果鎖已被經(jīng)釋放 再次嘗試獲取鎖
if (compareAndSetState(0, acquires)) { //直接嘗試把當前只設(shè)置成1,如果成功,把owner設(shè)置自己,并且退出
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) { // 如果當前線程為鎖的擁有者
int nextc = c + acquires; //這里就是重入鎖的概念,如果還是自己,則進行加1操作,因為釋放和獲取一定要是對等的
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc); // 累加 state 的值 此段代碼 實現(xiàn)了重入鎖
return true;
}
return false; //當前鎖被其他線程占用,退出。
}
/**
* 釋放鎖,默認releases傳1
*/
protected final boolean tryRelease(int releases) {
int c = getState() - releases; //獲取當前的鎖的狀態(tài)并且減1,因為要釋放鎖
if (Thread.currentThread() != getExclusiveOwnerThread()) //如果當前自己不是鎖的持有者,只有自己才能釋放鎖
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) { //釋放成功
free = true;
setExclusiveOwnerThread(null);
}
setState(c); //重新設(shè)置成狀態(tài)
return free;
}
/**
* 如果當前線程獨占著鎖,返回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();
}
/**
* 條件隊列
*/
final ConditionObject newCondition() {
return new ConditionObject();
}
/**
* 返回鎖的擁有者的線程
* 當前狀態(tài)為0返回null,說明在等待中
* 當前狀態(tài)不為0返回當前線程
*/
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
/**
* 當前線程占著鎖返回 state,否則返回0
*/
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
/**
* state狀態(tài)不為0標識上鎖,為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)造方法,默認選擇非公平鎖
*/
public ReentrantLock() {
sync = new NonfairSync();
}
/**
* 構(gòu)造方法,true公平鎖,false非公平鎖
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
ReentrantLock繼承和實現(xiàn)分析
?? ReentrantLock implements Lock
? Sync extends AbstractQueuedSynchronizer
? 1.ReentrantLock實現(xiàn)Lock接口,Lock接口定義了加鎖、條件隊列、解鎖、加鎖(中斷異常)
? 2.Sync繼承AQS抽象類,實現(xiàn)了獨占鎖,作為基礎(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;
}
}
2. NonfairSync非公平鎖--內(nèi)部類
/**
* 非公平鎖的同步對象
*/
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() {
// 通過原子操作 改變上鎖狀態(tài)
if (compareAndSetState(0, 1)) // 變更成功,說明獲取鎖成功
setExclusiveOwnerThread(Thread.currentThread()); // 設(shè)置持有者為當前線程
else //變更失敗
acquire(1); //嘗試以獨占模式獲取鎖,如果失敗加入node節(jié)點到隊列中
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
/**
* 是否有等待線程
*/
public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
/**
* 是否有等待線程
*/
public final boolean hasQueuedThreads() {
return head != tail;
}
ReentrantLock總結(jié)
1)ReentrantLock是可重入的公平/非公平模式的獨占鎖。
2)ReentrantLock公平鎖往往沒有非公平鎖的效率高,但是,并不是任何場景都是以TPS作為唯一指標,公平鎖
能夠減少“饑餓”發(fā)生的概率,等待越久的請求越能夠得到優(yōu)先滿足。
網(wǎng)站名稱:ReentrantLock源碼分析--jdk1.8
URL地址:http://www.dlmjj.cn/article/jospjd.html