首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 多線程同步深度解析:正確使用 lock 關鍵字避免競態條件

     編輯:關於C#

問題背景:多線程環境下的資料競爭

在多線程程式設計中,多個線程同時存取共享資源(如變數、檔案、資料庫連線)時,若缺乏同步機制,極易發生競態條件,導致資料不一致或程式崩潰。C# 提供 lock 關鍵字作為互斥鎖的語法糖,是解決此類問題的基礎工具。

基礎語法與原理

public class SharedResource {
    private static readonly object _lockObj = new object();
    private int _counter = 0;

    public void Increment() {
        lock (_lockObj) {
            _counter++; // 非原子操作:讀取、加一、寫回
        }
    }
}

lock(obj) 編譯器會展開為 Monitor.Enter(obj) 與 Monitor.Exit(obj)(在 try/finally 區塊中確保釋放)。只有持有鎖的線程能進入臨界區,其他線程阻塞等待。

經典錯誤:鎖住錯誤的物件

場景:多實例共享靜態計數器

需求:多個郵件接收線程(每個郵箱一個實例)從 POP3 取信,存入 FTP,需按接收順序全域遞增編號。

錯誤示範

class EmailProcessor {
    public static int CurrentNumber = 0;

    public void Process() {
        // 錯誤:鎖住 this,每個實例的 this 不同,無法互斥
        lock (this) {
            int localNum = ++CurrentNumber;
        }
    }
}

原因:lock(this) 僅同步同一實例上的呼叫。多個 EmailProcessor 實例各自持有不同的 this,互不干擾,靜態變數 CurrentNumber 仍會發生競爭。

正確做法:共享靜態鎖物件

class EmailInfo {
    public static readonly object SyncRoot = new object();
    public static int CurrentNumber = 0;
}

class EmailProcessor {
    public void Process() {
        // 所有實例共用同一把鎖
        lock (EmailInfo.SyncRoot) {
            int localNum = ++EmailInfo.CurrentNumber;
        }
    }
}

核心原則:鎖物件必須是所有需同步的線程可見的同一個引用。靜態唯讀物件是最佳實踐。

進階注意事項

  • 避免鎖公開型別或字串:lock(typeof(MyClass)) 或 lock("string") 可能被外部代碼鎖住,導致死鎖。
  • 臨界區最小化:鎖內只放必要的共享資源操作,避免耗時 I/O、複雜計算。
  • 不可重入風險:Monitor 是可重入的,同一線程可多次 Enter,但需對應次數 Exit。
  • 效能考量:高爭用場景可考慮 Interlocked 原子操作、ReaderWriterLockSlim 讀寫分離、或無鎖資料結構。

最佳實踐模板

public class ThreadSafeCounter {
    private readonly object _syncLock = new object(); // 實例級同步
    // private static readonly object _syncLock = new object(); // 靜態級同步
    private int _count;

    public int Increment() {
        lock (_syncLock) {
            return ++_count;
        }
    }
}

掌握 lock 的正確用法,是編寫健壯多線程 C# 程式的基石。記住:共享資源、同一把鎖、最小臨界區。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved