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