本文整理自《CLR via C# 第三版》關於執行緒同步的核心觀念、兩種同步結構(使用者模式/核心模式)效能對比,並附上作者實測程式碼與結果分析。
執行緒同步三大代價
- 識別困難:需找出所有可能被多執行緒存取的資源,無法驗證同步是否正確/完整/過度。
- 效能損耗:短暫操作加上鎖申請/釋放,效能可能下降一個數量級。
- 增加執行緒建立與上下文切換:阻塞導致排程器建立更多執行緒維持吞吐量。
何時「不需要」同步?
- 唯讀資源:多執行緒同時讀取不可變物件(如
string、readonly 欄位)無需同步。
- 值型別或不可變型別:操作會建立新實例,非共享狀態。
- 非共享範圍:ThreadLocal、方法區域變數、非 static 欄位(每個實例獨立)。
FCL 執行緒安全承諾
- 所有 靜態方法 保證執行緒安全。
- 實例方法 不保證(效能考量),需自行同步。
- 自訂類庫建議遵循相同標準:靜態安全、實例不保證。
兩種同步結構對比
| 特性 | 使用者模式 | 核心模式 |
| 代表 | SpinLock, Interlocked | Mutex, Semaphore, AutoResetEvent, Monitor |
| 支援層級 | 硬體指令 (CAS) | 作業系統核心物件 |
| 速度 | 極快 (無模式切換) | 較慢 (Ring 3 → Ring 0) |
| 阻塞行為 | 忙碌等待 (消耗 CPU) | 釋放 CPU,進入等待狀態 |
| 功能彈性 | 僅支援互斥 | 支援逾時、等待多物件、跨進程同步 |
效能測試程式碼與結果
class Program
{
static void Main()
{
const int Iterations = 5_000_000;
int x = 0;
var sw = Stopwatch.StartNew();
// 使用者模式:SimpleSpinLock (Interlocked.Exchange)
var ssl = new SimpleSpinLock();
for (int i = 0; i < Iterations; i++) { ssl.Enter(); x++; ssl.Leave(); }
Console.WriteLine($"SimpleSpinLock: {sw.ElapsedMilliseconds:N0} ms");
// 核心模式:SimpleWaitLock (AutoResetEvent)
using (var swl = new SimpleWaitLock())
{
sw.Restart();
for (int i = 0; i < Iterations; i++) { swl.Enter(); x++; swl.Leave(); }
Console.WriteLine($"SimpleWaitLock: {sw.ElapsedMilliseconds:N0} ms");
}
}
}
struct SimpleSpinLock
{
private int _resourceInUse;
public void Enter() { while (Interlocked.Exchange(ref _resourceInUse, 1) != 0) { } }
public void Leave() { Thread.VolatileWrite(ref _resourceInUse, 0); }
}
class SimpleWaitLock : IDisposable
{
private readonly AutoResetEvent _free = new AutoResetEvent(true);
public void Enter() => _free.WaitOne();
public void Leave() => _free.Set();
public void Dispose() => _free.Close();
}
測試結果解讀
- 無競爭時:SpinLock 極快(僅數十 ns),WaitLock 需微秒級核心轉換。
- 高競爭時:SpinLock 空轉燒 CPU,WaitLock 釋放 CPU 更有利系統整體吞吐。
- 實務建議:短關鍵區、低競爭用 SpinLock/Interlocked;長關鍵區、高競爭、需逾時/跨進程用核心物件。
Monitor 與 lock 關鍵字
C# lock(obj) 編譯為 Monitor.Enter/Exit,屬核心模式混合實作:先嘗試使用者模式自旋,失敗再進核心等待,兼顧效能與彈性,是最常用的同步原語。
- 上一篇文章: 淺談 .NET 多執行緒與平行運算(十四):平行運算前言與 ASP.NET 避坑指南
- 下一篇文章: 深入探討 .NET 多線程與並行計算(十二):CLR via C# 第三版閱讀筆記(上)
Copyright ©
程式碼之家 All Rights Reserved