共用方式為


已排入佇列的微調鎖定

已排入佇列的 微調鎖定是微調鎖定的變體,適用於高度競爭的鎖定。 傳統、未排入佇列的微調鎖定是較佳的選擇,適用於輕競爭或較短的持續時間鎖定。

使用佇列微調鎖定的優點包括:

  1. 降低處理器爭用:當多個線程嘗試同時取得鎖定時,傳統微調鎖定可能會導致大量的處理器爭用,因為它們會持續迴圈(或「微調」)檢查鎖定狀態。 這可能會降低系統效能,特別是在多處理器系統上。 已排入佇列的微調鎖定可藉由將線程組織到佇列來減輕此問題。 當線程取得鎖定時,只有下一行會主動旋轉,等候取得鎖定。 這樣可減少旋轉時浪費的CPU週期,特別是鎖定持續較長的時間。

  2. 公平和避免饑餓:基本旋轉鎖定的問題之一是缺乏公平性;如果其他線程持續取得和釋放它,線程可能會餓死,永遠不會取得鎖定。 已排入佇列的微調鎖定可藉由確保線程依照嘗試的順序取得鎖定,來解決此問題。 此循序處理可防止饑餓,並確保所有線程都會隨著時間而提供服務。

  3. 延展性:當系統中處理器或核心數目增加時,同步處理機制的效率會變得對效能至關重要。 佇列的微調鎖定比傳統微調鎖定更可調整,因為它們會藉由將所有核心的作用中旋轉降至最低,以減少處理器的額外負荷。 這在高效能、多核心系統中特別重要,因為驅動程式效率可能會直接影響整體系統效能。

  4. 有效使用系統資源:藉由減少不必要的處理器旋轉,佇列微調鎖定可讓系統更有效率地使用其資源。 這不僅可改善設備驅動器的效能,而且對系統的整體回應性和耗電量產生積極影響,這在區分電源的環境中特別有用。

  5. 簡單性和可靠性:儘管他們在減少爭用和改善公平性方面有優勢,但佇列的微調鎖定會從開發人員身上抽象化複雜度。 它們提供簡單且可靠的機制來保護共享資源,而不需要開發人員實作複雜的鎖定邏輯。 這種簡單性可降低與不當鎖定處理相關的 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,它可以改為呼叫 KeAcquireInStackQueuedSpinLockAtDpcLevelKeReleaseInStackQueuedSpinLockFromDpcLevel。