簡單來講講C#中的鎖
?? 簡單來講講C#中的鎖
? 前言
今天來說說C#中的鎖,鎖在日常開發中還是很常用的,但是用的不得當,或者騷操作比較多那么就會導致死鎖,從而導致系統崩潰。
后面我會出一系列文章,來講講C#里面的代碼和技巧,通過不斷的學習積累,以達到我的跳槽目標。
文章中有任何錯誤的地方都可以指出,博主也在不斷的學習中~
?? 簡述
下面問問AI來簡單了解下什么是鎖,AI分析還是挺詳細的。
?? 通俗理解
- 在現實生活里,鎖就像一把門鎖。
- 如果一個人進了房間并把門反鎖,別人就得在外面等他出來。
- 等里面的人出來并開鎖后,下一個人才能進去。
?? 編程里的“鎖”也是一樣的:
它保證同一時刻只有一個線程能進入臨界區(共享資源的代碼塊),從而避免混亂。
?? 技術定義
在 并發編程 中,鎖(Lock)是一種同步機制,用來 控制多個線程對共享資源的并發訪問。
- 沒有鎖時:多個線程可能同時修改同一個變量、文件、數據庫記錄 → 造成 數據競爭 (Race Condition)。
- 有了鎖后:一個線程進入臨界區時,其它線程必須等待 → 保證 數據一致性。
?? 鎖的關鍵特性
- 互斥性
- 一次只能有一個線程持有鎖。
- 其他線程必須等待。
- 可見性
- 線程釋放鎖前的修改,對之后獲取鎖的線程是可見的。
- 可重入性(C# 的 lock 是可重入的)
- 同一線程可以多次進入同一把鎖,而不會死鎖自己。
?? 舉例
下面就舉個例子講講什么情況下就需要用到鎖。
int a = 0;
// 并行++
Parallel.For(0, 1000, _ => {
a++;
});
// 會發現 a 的值小于 1000,因為并行操作導致了線程之間的競爭。
Console.WriteLine(a);
正常情況下,a的值應該是等于1000的,但由于這里使用了Parallel.For,會導致多個線程對同一個值進行++操作,從而導致最終的結果沒有1000次。
那么如何避免這種情況呢,可以使用鎖去避免。
// 使用鎖解決線程競爭問題
object obj = new object();
int b = 0;
Parallel.For(0, 1000, _ => {
lock (obj) {
b++;
}
});
// 現在 b 的值一定是 1000,因為鎖確保了同一時間只有一個線程可以執行 b++ 操作。
Console.WriteLine(b);
這里使用了一個object類型作為鎖對象,這也是常見的鎖對象,不一定非得使用object類型,其他引用類型也行。
??? 運行結果

?? .net9 新的鎖對象
上面已經通過簡單的例子了解到了什么是鎖,已經怎么使用鎖,那么在.net9中可以直接使用lock對象作為鎖。
?? 在使用
.net9創建項目時,如果使用object類型的鎖,rider編輯器會提示使用Lock類型作為鎖。
? 老寫法
public class Lock
{
private readonly object _lock = new();
public void Foo()
{
lock (_lock)
{
Thread.Sleep(3000);
Console.WriteLine("In Foo");
}
}
}

? 新寫法
public class Deadlock
{
private readonly Lock _lock = new();
public void Foo()
{
lock (_lock)
{
Thread.Sleep(3000);
Console.WriteLine("In Foo");
}
}
}
?? 比較
| 特性 | 傳統的 object + lock(obj)(Monitor-based) |
用 System.Threading.Lock + lock(newLock) |
|---|---|---|
| 鎖對象類型意圖性 | 任意引用類型,不專門為鎖“設計” | 專門的鎖類型,用意明確 |
| 編譯器識別/處理 | 用 Monitor.Enter/Exit; lock(object) 被編譯器轉換為 Monitor 操作 |
如果 lock 的目標是 Lock 類型,編譯器 special-case 使用 EnterScope()/Dispose() 的新方式 |
| 內部機制 | 使用 Monitor、SyncBlocks、Thin locks 等,涉及 object header,可能有額外開銷 |
新語義可以減少某些 Monitor 的開銷,scope 塊式釋放鎖,可能在某些場景性能更優 |
| 性能 | 在高并發且鎖競爭嚴重的場景下性能可能成為瓶頸 | 在同樣場景下可有更好的性能(但具體提升依賴于運行情況和 contention) |
| 可讀性/安全性 | 用 object,可能誤用;不容易一眼看出這是鎖對象 |
用 Lock 類型,代碼語義直接告訴你“這是用來加鎖的” |
?? 總結
鎖是并發編程里的“雙刃劍”。
- 用得好 ?? 能保證線程安全,避免數據錯亂。
- 用不好 ?? 容易掉進性能陷阱,甚至導致死鎖,拖垮整個系統。
在 .NET 9 之前,我們習慣用 object 作為鎖對象,但語義模糊,容易被誤用。
而新的 System.Threading.Lock 專門為鎖而生,讓代碼更直觀,也在某些場景下帶來性能提升。
所以:
- 寫 demo、小項目 → 用
lock(object)依舊沒問題。 - 寫業務、追求可維護性和性能 → 建議上手 .NET 9 的
Lock,讓代碼更優雅、更安全。
?? 學會合理使用鎖,能讓你的程序更加穩定,也能減少“背鍋”的機會。
?? 相關鏈接
- 【.NET 9新增的鎖對象(Lock)是怎么一回事?】 https://www.bilibili.com/video/BV1rLp2zMEua/?share_source=copy_web&vd_source=fce337a51d11a67781404c67ec0b5084

浙公網安備 33010602011771號