目錄
1. 鎖機制 (Locking Mechanisms)
(1)?lock?關鍵字
(2)?Monitor?類
2. 跨進程互斥機制
3. 信號量機制
(1)?Semaphore?和?SemaphoreSlim
4. 讀寫鎖機制
(1)?ReaderWriterLockSlim
5. 原子操作機制
(1)?Interlocked?類
6. 自旋鎖機制
(1)?SpinLock
線程互斥是一種保證在同一時刻只有一個線程能夠訪問共享資源的機制。它是一種排他性的訪問控制,目的是防止多個線程同時對共享資源進行讀寫操作而導致的數據不一致或其他錯誤。比如多個線程同時對一個銀行賬戶進行取款操作,如果不進行互斥控制,就可能出現賬戶余額錯誤的情況。
在 .NET 中,線程互斥(Mutual Exclusion)有多種實現方式,以下是 .NET 中常見的線程互斥實現方式:
實現方式 | 特點 | 使用場景 |
lock關鍵字 | 簡單易用,自動管理鎖 | 進程內同步 |
Monitor類 | 更細粒度控制鎖 | 顯式控制鎖的場景 |
Mutex類 | 支持跨進程 | 多進程間同步 |
信號量Semaphore? | 限制最大并發數 | 控制資源訪問數量 |
讀寫鎖 ReaderWriterLockSlim | 允許多線程同時讀,但只允許一個線程寫 | 讀多寫少的場景 |
Interlocked類 | 原子操作,高效 | 簡單數值操作 |
自旋鎖SpinLock | 自旋等待鎖,避免上下文切換 | 短時間臨界區 |
根據具體需求選擇合適的線程互斥機制,能夠有效提升程序的性能和可靠性。
1. 鎖機制 (Locking Mechanisms)
(1)?lock?關鍵字
- 原理:?lock?是 C# 中的一個語法糖,它實際上是調用了?Monitor.Enter?和?Monitor.Exit?方法來實現的。當一個線程執行到?lock?語句塊時,它會嘗試獲取鎖對象上的排他鎖。如果成功獲取,則進入臨界區執行代碼;否則,該線程將被阻塞直到鎖可用。
- 特點:
- 簡單易用,適用于單一應用程序域內的線程同步。
- 自動處理異常情況下的鎖釋放。
- 示例:
private readonly object _lockObject = new object();public void CriticalSection()
{lock (_lockObject){// 訪問共享資源的代碼}
}
(2)?Monitor?類
- 原理:?Monitor?提供了比?lock?更靈活的同步機制,允許手動控制進入和退出臨界區。通過調用?Monitor.Enter?獲取鎖,Monitor.Exit?釋放鎖。此外,還支持條件變量(Wait,?Pulse,?PulseAll)以實現更復雜的同步邏輯。
- 特點:
- 支持超時等待獲取鎖的能力。
- 可以與條件變量一起使用,支持復雜的同步模式。
- 示例:
private readonly object _lockObject = new object();public void CriticalSection()
{try{Monitor.Enter(_lockObject);// 訪問共享資源的代碼}finally{Monitor.Exit(_lockObject);}
}
2. 跨進程互斥機制
(1)?Mutex?類
- 原理:?Mutex?是一種內核級別的同步對象,可以用于跨進程的線程同步。當一個線程獲取了?Mutex?對象的所有權時,其他線程會被阻塞,直到該線程釋放?Mutex。
- 特點:
- 支持跨進程同步。
- 性能較?lock?和?Monitor?稍低,因為它是內核對象。
- 示例:
using System.Threading;private static Mutex _mutex = new Mutex();public void CriticalSection()
{_mutex.WaitOne(); // 獲取鎖try{// 訪問共享資源的代碼}finally{_mutex.ReleaseMutex(); // 釋放鎖}
}
3. 信號量機制
(1)?Semaphore?和?SemaphoreSlim
- 原理:?信號量是一種允許多個線程同時訪問共享資源的同步機制,但限制最大并發數。Semaphore?支持跨進程,而?SemaphoreSlim?是輕量級版本,僅限于當前進程內使用。
- 特點:
- Semaphore?支持跨進程同步。
- SemaphoreSlim?性能更高,適合單進程場景。
示例:?(SemaphoreSlim)
using System.Threading;private static SemaphoreSlim _semaphore = new SemaphoreSlim(1); // 最大并發數為 1public async Task CriticalSectionAsync()
{await _semaphore.WaitAsync();try{// 訪問共享資源的代碼}finally{_semaphore.Release();}
}
4. 讀寫鎖機制
(1)?ReaderWriterLockSlim
- 原理:?ReaderWriterLockSlim?是一種優化的讀寫鎖,允許多個線程同時讀取共享資源,但只允許一個線程寫入資源。通過?EnterReadLock、EnterWriteLock?和?EnterUpgradeableReadLock?方法分別管理讀鎖、寫鎖和可升級的讀鎖。
- 特點:
- 適合讀多寫少的場景。
- 提高了讀操作的并發性能。
- 示例:
private static ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();public void ReadOperation()
{_rwLock.EnterReadLock();try{// 讀取共享資源的代碼}finally{_rwLock.ExitReadLock();}
}public void WriteOperation()
{_rwLock.EnterWriteLock();try{// 寫入共享資源的代碼}finally{_rwLock.ExitWriteLock();}
}
5. 原子操作機制
(1)?Interlocked?類
- 原理:?Interlocked?提供了一些原子操作方法,用于對簡單數據類型(如整數)進行線程安全的操作。這些操作在硬件級別上保證了原子性,無需顯式加鎖。
- 特點:
- 高效,無需顯式加鎖。
- 適用于簡單的數值操作。
- 示例:
using System.Diagnostics.Metrics;private int _counter = 0;public void IncrementCounter()
{Interlocked.Increment(ref _counter);
}public void DecrementCounter()
{Interlocked.Decrement(ref _counter);
}
6. 自旋鎖機制
(1)?SpinLock
- 原理:?SpinLock?是一種自旋鎖,線程會不斷循環檢查鎖是否可用,而不是進入等待狀態。這種方式避免了上下文切換開銷,但在長時間鎖定時會浪費 CPU 資源。
- 特點:
- 適合非常短的臨界區。
- 避免上下文切換的開銷。
- 示例:
using System.Threading;private SpinLock _spinLock = new SpinLock();public void CriticalSection()
{bool lockTaken = false;try{_spinLock.Enter(ref lockTaken);// 訪問共享資源的代碼}finally{if (lockTaken)_spinLock.Exit();}
}