mysql的锁是公平的么_lock 默认公平锁还是非公平锁?公平锁是如何定义?如何实现...
ReentrantLock的實現(xiàn)是基于其內(nèi)部類FairSync(公平鎖)和NonFairSync(非公平鎖)實現(xiàn)的。 其可重入性是基于Thread.currentThread()實現(xiàn)的: 如果當(dāng)前線程已經(jīng)獲得了執(zhí)行序列中的鎖, 那執(zhí)行序列之后的所有方法都可以獲得這個鎖。
公平鎖:
公平和非公平鎖的隊列都基于鎖內(nèi)部維護(hù)的一個雙向鏈表,表結(jié)點Node的值就是每一個請求當(dāng)前鎖的線程。公平鎖則在于每次都是依次從隊首取值。
鎖的實現(xiàn)方式是基于如下幾點:
表結(jié)點Node和狀態(tài)state的volatile關(guān)鍵字。
sum.misc.Unsafe.compareAndSet的原子操作(見附錄)。
非公平鎖:
在等待鎖的過程中, 如果有任意新的線程妄圖獲取鎖,都是有很大的幾率直接獲取到鎖的。
ReentrantLock鎖都不會使得線程中斷,除非開發(fā)者自己設(shè)置了中斷位。
ReentrantLock獲取鎖里面有看似自旋的代碼,但是它不是自旋鎖。
ReentrantLock公平與非公平鎖都是屬于排它鎖。
公平鎖和非公平鎖在說的獲取上都使用到了 volatile 關(guān)鍵字修飾的state字段, 這是保證多線程環(huán)境下鎖的獲取與否的核心。
但是當(dāng)并發(fā)情況下多個線程都讀取到 state == 0時,則必須用到CAS技術(shù),一門CPU的原子鎖技術(shù),可通過CPU對共享變量加鎖的形式,實現(xiàn)數(shù)據(jù)變更的原子操作。
volatile 和 CAS的結(jié)合是并發(fā)搶占的關(guān)鍵。
公平鎖的實現(xiàn)機(jī)理在于每次有線程來搶占鎖的時候,都會檢查一遍有沒有等待隊列,如果有, 當(dāng)前線程會執(zhí)行如下步驟:
/**
* 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;
}
其中hasQueuedPredecessors是用于檢查是否有等待隊列的。
非公平鎖在實現(xiàn)的時候多次強(qiáng)調(diào)隨機(jī)搶占:
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
當(dāng)當(dāng)前擁有鎖的線程釋放鎖之后, 且非公平鎖無線程搶占,就開始線程喚醒的流程。
通過tryRelease釋放鎖成功,調(diào)用LockSupport.unpark(s.thread);?終止線程阻塞
private void unparkSuccessor(Node node) {
// 強(qiáng)行回寫將被喚醒線程的狀態(tài)
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
// s為h的下一個Node, 一般情況下都是非Null的
if (s == null || s.waitStatus > 0) {
s = null;
// 否則按照FIFO原則尋找最先入隊列的并且沒有被Cancel的Node
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
// 再喚醒它
if (s != null)
LockSupport.unpark(s.thread);
}
非公平鎖性能高于公平鎖性能的原因:
在恢復(fù)一個被掛起的線程與該線程真正運(yùn)行之間存在著嚴(yán)重的延遲。
假設(shè)線程A持有一個鎖,并且線程B請求這個鎖。由于鎖被A持有,因此B將被掛起。當(dāng)A釋放鎖時,B將被喚醒,因此B會再次嘗試獲取這個鎖。與此同時,如果線程C也請求這個鎖,那么C很可能會在B被完全喚醒之前獲得、使用以及釋放這個鎖。這樣就是一種雙贏的局面:B獲得鎖的時刻并沒有推遲,C更早的獲得了鎖,并且吞吐量也提高了。
當(dāng)持有鎖的時間相對較長或者請求鎖的平均時間間隔較長,應(yīng)該使用公平鎖。在這些情況下,插隊帶來的吞吐量提升(當(dāng)鎖處于可用狀態(tài)時,線程卻還處于被喚醒的過程中)可能不會出現(xiàn)。
總結(jié)
以上是生活随笔為你收集整理的mysql的锁是公平的么_lock 默认公平锁还是非公平锁?公平锁是如何定义?如何实现...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎样隐藏电脑开始菜单(怎样隐藏电脑开始菜
- 下一篇: 笔记本电脑那个是删除键(笔记本电脑那个是