lock/Monitor/ReaderWriterLockSlim/SemaphoreSlim)。Mutex/Semaphore/EventWaitHandle)。ReaderWriterLockSlim。Interlocked/Concurrent 集合/Channels (Core 3.0+)。// ❌ 鎖定 this:外部也可能 lock(this) 造成死鎖
lock (this) { ... }
// ❌ 鎖定 Type:公開型別,全程序共享,極易衝突
lock (typeof(MyClass)) { ... }
// ❌ 鎖定字串:字串驻留導致不同代碼鎖定同一物件
lock ("myLock") { ... }
// ❌ 鎖定值型別:每次裝箱產生新物件,鎖完全失效
int x = 0; lock (x) { ... }
private readonly object _lockObj = new object();
public void AccessResource() {
lock (_lockObj) { // Monitor.Enter/Exit 語法糖
// 臨界區:存取檔案、序列埠、非執行緒安全物件
}
}
// 命名 Mutex:作業系統層面全域唯一
using (var mutex = new Mutex(false, "Global\\MyApp_ResourceLock")) {
if (mutex.WaitOne(TimeSpan.FromSeconds(10))) {
try { AccessSharedResource(); }
finally { mutex.ReleaseMutex(); }
}
else { throw new TimeoutException("取得鎖逾時"); }
}
Global\\ 前綴:跨 Terminal Session 可見 (服務/系統帳號需求)。try/finally 確保釋放,否則永久阻塞。var queue = new Queue<int>();
var signal = new AutoResetEvent(false); // 自動重置:喚醒一個即歸零
// 生產者
Task.Run(() => {
while (true) {
var item = Produce();
lock (queue) queue.Enqueue(item);
signal.Set(); // 通知消費者
}
});
// 消費者
Task.Run(() => {
while (true) {
signal.WaitOne(); // 阻塞等待
int item;
lock (queue) { if (queue.Count > 0) item = queue.Dequeue(); else continue; }
Consume(item);
}
});
var buffer = new BlockingCollection<int>(boundedCapacity: 100); // 內建阻塞、限流
// 生產者
Task.Run(() => {
try {
while (!buffer.IsAddingCompleted) buffer.Add(Produce()); // 滿時自動阻塞
} finally { buffer.CompleteAdding(); }
});
// 消費者
Task.Run(() => {
foreach (var item in buffer.GetConsumingEnumerable()) // 空時阻塞,CompleteAdding 時結束
Consume(item);
});
優點:無鎖程式碼、內建背壓、可限容量、支援多生產/多消費、可取消 (CancellationToken)。
var cts = new CancellationTokenSource();
var buffer = new BlockingCollection<WorkItem>(100);
var producers = Enumerable.Range(0, 3).Select(i => Task.Run(() => {
while (!cts.Token.IsCancellationRequested) {
var item = Produce();
if (!buffer.TryAdd(item, 1000, cts.Token)) break; // 逾時/取消
}
}, cts.Token)).ToArray();
var consumers = Enumerable.Range(0, 5).Select(i => Task.Run(() => {
foreach (var item in buffer.GetConsumingEnumerable(cts.Token))
Process(item);
}, cts.Token)).ToArray();
// 關閉流程
cts.CancelAfter(TimeSpan.FromMinutes(5));
Task.WaitAll(producers);
buffer.CompleteAdding();
Task.WaitAll(consumers);
| 原語 | 適用範圍 | 核心特性 | 典型場景 |
|---|---|---|---|
| lock (Monitor) | AppDomain 內 | 互斥、可重入、語法簡潔 | 保護共享欄位/集合 |
| Mutex | 跨進程 | 核心物件、命名全域唯一 | 單一實例應用、跨進程資源 |
| SemaphoreSlim | AppDomain 內 | 計數信號、非阻塞等待 | 限流、連線池控制 |
| AutoResetEvent | AppDomain 內 | 單一喚醒、自動重置 | 簡單生產消費 (舊代碼) |
| ManualResetEventSlim | AppDomain 內 | 廣播喚醒、手動重置 | 階段性啟動信號 |
| ReaderWriterLockSlim | AppDomain 內 | 讀共享/寫獨佔 | 快取、設定讀多寫少 |
| BlockingCollection | AppDomain 內 | 生產消費模式封裝、背壓 | 管道處理、工作佇列 |
| Interlocked | AppDomain 內 | 原子操作 (CAS)、無鎖 | 計數器、旗標、無鎖資料結構 |
| Concurrent 集合 | AppDomain 內 | 無鎖/細粒度鎖、高併發 | Dictionary/Queue/Stack/Bag 共享 |
SemaphoreSlim.WaitAsync 或 AsyncLock (Stephen Cleary)。