WCF 服務在 InstanceContextMode.Single + ConcurrencyMode.Multiple 模式下為單一實例多執行緒存取,必須自行處理併發同步。本文比較 .NET 主流同步機制在 WCF 中的應用。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Hello : IHello {
private int _counter;
private string _result;
private Mutex _mutex = new Mutex();
private Semaphore _semaphore = new Semaphore(1, 1);
private static readonly object _objLock = new object();
// ...
}
private void ExecuteNone() {
CircleCounter(); // 會出現重複計數:1,2,2,3,4,5,5,6...
}
private void ExecuteMutex() {
try {
_mutex.WaitOne();
CircleCounter();
} finally {
_mutex.ReleaseMutex();
}
}
支援跨進程同步,較重量級,適合命名 Mutex 協調多進程。
private void ExecuteSemaphore() {
try {
_semaphore.WaitOne(); // 取得一個槽位
CircleCounter();
} finally {
_semaphore.Release(); // 釋放槽位
}
}
可限制同時存取執行緒數(建構式 new Semaphore(初始, 最大)),適合連線池、資源池控制。
private void ExecuteMonitor() {
try {
Monitor.Enter(this);
CircleCounter();
} finally {
Monitor.Exit(this);
}
}
lock 的編譯器展開形式,支援 TryEnter、Wait/Pulse 進階同步。
private void ExecuteLock() {
lock (_objLock) {
CircleCounter();
}
}
最常用、可讀性最好,編譯為 Monitor.Enter/Exit + try/finally。
客戶端啟動兩個執行緒同時呼叫 Counter(LockType),每執行緒迴圈 10 次,間隔 20ms 模擬併發:
private void CircleCounter() {
for (int i = 0; i < 10; i++) {
var counter = _counter;
Thread.Sleep(20); // 模擬併發窗口
_counter = ++counter;
_result += _counter + "|";
}
}
| 同步機制 | 結果 | 說明 |
|---|---|---|
| None | 出現重複計數 | 競爭條件,非執行緒安全 |
| Mutex | 1~20 連續無重複 | 正確同步 |
| Semaphore | 1~20 連續無重複 | 正確同步 |
| Monitor | 1~20 連續無重複 | 正確同步 |
| Lock | 1~20 連續無重複 | 正確同步 |
Increment, CompareExchange),適用於單一變數更新,效能最佳| 場景 | 建議機制 |
|---|---|
| 單一進程內簡單互斥 | lock / Monitor |
| 跨進程同步 | 命名 Mutex |
| 限制並存取數量 (連線池) | Semaphore / SemaphoreSlim |
| 高頻率單一變數更新 | Interlocked |
| 讀多寫少、複雜同步邏輯 | ReaderWriterLockSlim |
WCF 併發控制的核心原則:識別共享狀態 → 選擇適當同步機制 → 縮小臨界區範圍 → 避免死鎖。