//默認(rèn)實現(xiàn)為非公平鎖微猖,這個構(gòu)造方法相當(dāng)于new ReentrantLock(false) false 使用非公平鎖
public ReentrantLock() {
sync = new NonfairSync();
}
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
//判斷當(dāng)前線程是否被中斷
if (Thread.interrupted())
throw new InterruptedException();
//2種方式獲取鎖方法
return tryAcquire(arg) ||
doAcquireNanos(arg, nanosTimeout);
}
//try Acquire(arg) 最終會調(diào)用這個方法
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
//獲取當(dāng)前鎖狀態(tài)
int c = getState();
//如果鎖是空閑時
if (c == 0) {
//cas 更改state值
if (compareAndSetState(0, acquires)) {
//成功的話設(shè)置當(dāng)前鎖的獨占線程為當(dāng)前線程
setExclusiveOwnerThread(current);
return true;
}
}
//鎖已經(jīng)被持有且持有者為當(dāng)前線程
else if (current == getExclusiveOwnerThread()) {
//state增加
int nextc = c + acquires;
//如果增加后小于0.則報錯
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
//設(shè)置新state值
setState(nextc);
return true;
}
return false;
}
//以獨占定時模式獲取鎖 轿曙,在指定時間nanosTimeout內(nèi)不斷獲取鎖犀勒,并且始終都是當(dāng)前節(jié)點的上一個節(jié)點先獲取到鎖
//應(yīng)該是公平鎖的獲取方式
private boolean doAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (nanosTimeout <= 0L)
return false;
//獲取到超時的時間點
final long deadline = System.nanoTime() + nanosTimeout;
//加入隊列末尾
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
//獲取當(dāng)前節(jié)點的上一個節(jié)點
final Node p = node.predecessor();
//如果是頭節(jié)點且獲取鎖成功 tryAcquire(非公平鎖方法)
if (p == head && tryAcquire(arg)) {
//將頭節(jié)點變?yōu)楫?dāng)前節(jié)點
setHead(node);
//頭節(jié)點認(rèn)為設(shè)置null副女,方便垃圾回收
p.next = null; // help GC
failed = false;
return true;
}
nanosTimeout = deadline - System.nanoTime();
//如果超時,則直接返回
if (nanosTimeout <= 0L)
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
//虛假中斷
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
} finally {
//失敗的話垦写,取消獲取
if (failed)
cancelAcquire(node);
}
}
//加入等待隊列
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
//最新的對尾元素
Node pred = tail;
//如果隊列存在
if (pred != null) {
node.prev = pred;
//設(shè)置當(dāng)前隊尾元素為當(dāng)前任務(wù)
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
//初始化隊列
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
//設(shè)置當(dāng)前頭元素
if (compareAndSetHead(new Node()))
tail = head;
} else {
//加入隊為
node.prev = t;
//設(shè)置當(dāng)前隊尾元素
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/
//說明需要通知后續(xù)節(jié)點
return true;
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
//大于0說明該搶鎖任務(wù)被取消了
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
//waitStatus 為0 或者-3時 說明需要重試 設(shè)置waitStatus的值
//設(shè)置一個信號量吕世,為后續(xù)喚醒
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
//公平鎖的加鎖方式
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
//如果當(dāng)前線程前面有一個排隊線程,則等待梯投,如果當(dāng)前線程位于隊列的頭部或隊列為空命辖,則直接獲取
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//如果當(dāng)前線程是持有鎖線程,則直接獲取
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源碼解析
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
- 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來窍荧,“玉大人辉巡,你說我怎么就攤上這事∪锿耍” “怎么了郊楣?”我有些...
- 文/不壞的土叔 我叫張陵,是天一觀的道長咕痛。 經(jīng)常有香客問我痢甘,道長,這世上最難降的妖魔是什么茉贡? 我笑而不...
- 正文 為了忘掉前任,我火速辦了婚禮者铜,結(jié)果婚禮上腔丧,老公的妹妹穿的比我還像新娘。我一直安慰自己作烟,他們只是感情好愉粤,可當(dāng)我...
- 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拿撩,像睡著了一般衣厘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上压恒,一...
- 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼毛仪!你這毒婦竟也來了搁嗓?” 一聲冷哼從身側(cè)響起,我...
- 正文 年R本政府宣布脐雪,位于F島的核電站厌小,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏战秋。R本人自食惡果不足惜璧亚,卻給世界環(huán)境...
- 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望脂信。 院中可真熱鬧癣蟋,春花似錦、人聲如沸狰闪。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽埋泵。三九已至幔欧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丽声,已是汗流浹背礁蔗。 一陣腳步聲響...
推薦閱讀更多精彩內(nèi)容
- 開發(fā)中需要注意喊巍,一定要在finally塊中釋放鎖屠缭。 公平鎖的解鎖過程 tryRelease(arg):該方法有AQ...
- 之前的acquire函數(shù)會先調(diào)用tryAcquire去嘗試獲得鎖,這個在每個具體類中實現(xiàn)崭参,這里看Reentrant...
- 一呵曹、AQS是什么 AQS是AbstractQueuedSynchronizer的簡稱,它是Java各種鎖的底層實現(xiàn)...
- 大家好,我是小黑奄喂,一個在互聯(lián)網(wǎng)茍且偷生的農(nóng)民工铐殃。 在Java并發(fā)編程中,經(jīng)常會用到鎖跨新,除了Synchronized...