已排入佇列的微調鎖定
已排入佇列的 微調鎖定是微調鎖定的變體,適用於高度競爭的鎖定。 傳統、未排入佇列的微調鎖定是較佳的選擇,適用於輕競爭或較短的持續時間鎖定。
使用佇列微調鎖定的優點包括:
降低處理器爭用:當多個線程嘗試同時取得鎖定時,傳統微調鎖定可能會導致大量的處理器爭用,因為它們會持續迴圈(或「微調」)檢查鎖定狀態。 這可能會降低系統效能,特別是在多處理器系統上。 已排入佇列的微調鎖定可藉由將線程組織到佇列來減輕此問題。 當線程取得鎖定時,只有下一行會主動旋轉,等候取得鎖定。 這樣可減少旋轉時浪費的CPU週期,特別是鎖定持續較長的時間。
公平和避免饑餓:基本旋轉鎖定的問題之一是缺乏公平性;如果其他線程持續取得和釋放它,線程可能會餓死,永遠不會取得鎖定。 已排入佇列的微調鎖定可藉由確保線程依照嘗試的順序取得鎖定,來解決此問題。 此循序處理可防止饑餓,並確保所有線程都會隨著時間而提供服務。
延展性:當系統中處理器或核心數目增加時,同步處理機制的效率會變得對效能至關重要。 佇列的微調鎖定比傳統微調鎖定更可調整,因為它們會藉由將所有核心的作用中旋轉降至最低,以減少處理器的額外負荷。 這在高效能、多核心系統中特別重要,因為驅動程式效率可能會直接影響整體系統效能。
有效使用系統資源:藉由減少不必要的處理器旋轉,佇列微調鎖定可讓系統更有效率地使用其資源。 這不僅可改善設備驅動器的效能,而且對系統的整體回應性和耗電量產生積極影響,這在區分電源的環境中特別有用。
簡單性和可靠性:儘管他們在減少爭用和改善公平性方面有優勢,但佇列的微調鎖定會從開發人員身上抽象化複雜度。 它們提供簡單且可靠的機制來保護共享資源,而不需要開發人員實作複雜的鎖定邏輯。 這種簡單性可降低與不當鎖定處理相關的 Bug 可能性,進而提升驅動程式的可靠性。
以下是簡化的代碼段,示範 Windows 核心模式驅動程式中已排入佇列微調鎖定的已描述作業。 此範例示範如何使用 KeInitializeSpinLock 來宣告和初始化微調鎖定,然後使用 KeAcquireInStackQueuedSpinLock 和 KeReleaseInStackQueuedSpinLock 分別取得和釋放鎖定。
KSPIN_LOCK SpinLock;
KLOCK_QUEUE_HANDLE LockHandle;
// Initialize the spin lock
KeInitializeSpinLock(&SpinLock);
// Assume this function is called in some kind of context where
// the below operations make sense, e.g., in a device I/O path
// Acquire the queued spin lock
KeAcquireInStackQueuedSpinLock(&SpinLock, &LockHandle);
// At this point, the current thread holds the spin lock.
// Perform thread-safe operations here.
// ...
// Release the queued spin lock
KeReleaseInStackQueuedSpinLock(&LockHandle);
驅動程式會配置KLOCK_QUEUE_HANDLE結構,其會透過指向 KeAcquireInStackQueuedSpinLock 的指標傳遞。 驅動程式會在釋放微調鎖定時,透過KeReleaseInStackQueuedSpinLock的指標傳遞相同的結構。
驅動程式通常會在每次取得鎖定時,在堆疊上配置 結構。 驅動程式不應將 結構配置為其裝置內容的一部分,然後從多個線程共用相同的結構。
驅動程式不得混合對佇列微調鎖定例程的呼叫,以及相同微調鎖定上的一 般 KeXxxSpinLock 例程。
如果驅動程式已經在 IRQL = DISPATCH_LEVEL,它可以改為呼叫 KeAcquireInStackQueuedSpinLockAtDpcLevel 和 KeReleaseInStackQueuedSpinLockFromDpcLevel。