?? 簡單來講講C#中的鎖
? 前言
今天來說說C#中的鎖,鎖在日常開發(fā)中還是很常用的,但是用的不得當,或者騷操作比較多那么就會導致死鎖,從而導致系統(tǒng)崩潰。
?? 簡述
?? 通俗理解
- 在現(xiàn)實生活里,鎖就像一把門鎖。
- 如果一個人進了房間并把門反鎖,別人就得在外面等他出來。
- 等里面的人出來并開鎖后,下一個人才能進去。
?? 編程里的“鎖”也是一樣的:
它保證同一時刻只有一個線程能進入臨界區(qū)(共享資源的代碼塊),從而避免混亂。
?? 技術(shù)定義
在 并發(fā)編程 中,鎖(Lock)是一種同步機制,用來 控制多個線程對共享資源的并發(fā)訪問。
- 沒有鎖時:多個線程可能同時修改同一個變量、文件、數(shù)據(jù)庫記錄 → 造成 數(shù)據(jù)競爭 (Race Condition)。
- 有了鎖后:一個線程進入臨界區(qū)時,其它線程必須等待 → 保證 數(shù)據(jù)一致性。
?? 鎖的關(guān)鍵特性
- 互斥性
- 可見性
- 可重入性(C# 的 lock 是可重入的)
?? 舉例
下面就舉個例子講講什么情況下就需要用到鎖。
int a = 0;
Parallel.For(0, 1000, _ => {
a++;
});
Console.WriteLine(a);
正常情況下,a的值應(yīng)該是等于1000
的,但由于這里使用了Parallel.For
,會導致多個線程對同一個值進行++
操作,從而導致最終的結(jié)果沒有1000次。
那么如何避免這種情況呢,可以使用鎖去避免。
object obj = new object();
int b = 0;
Parallel.For(0, 1000, _ => {
lock (obj) {
b++;
}
});
Console.WriteLine(b);
這里使用了一個object
類型作為鎖對象,這也是常見的鎖對象,不一定非得使用object類型,其他引用類型也行。
??? 運行結(jié)果

?? .net9 新的鎖對象
上面已經(jīng)通過簡單的例子了解到了什么是鎖,已經(jīng)怎么使用鎖,那么在.net9
中可以直接使用lock
對象作為鎖。
?? 在使用.net9
創(chuàng)建項目時,如果使用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");
}
}
}
?? 比較
特性 | 傳統(tǒng)的 object + lock(obj) (Monitor-based) | 用 System.Threading.Lock + lock(newLock) |
---|
鎖對象類型意圖性 | 任意引用類型,不專門為鎖“設(shè)計” | 專門的鎖類型,用意明確 |
編譯器識別/處理 | 用 Monitor.Enter/Exit ; lock(object) 被編譯器轉(zhuǎn)換為 Monitor 操作 | 如果 lock 的目標是 Lock 類型,編譯器 special-case 使用 EnterScope()/Dispose() 的新方式 |
內(nèi)部機制 | 使用 Monitor 、SyncBlocks、Thin locks 等,涉及 object header,可能有額外開銷 | 新語義可以減少某些 Monitor 的開銷,scope 塊式釋放鎖,可能在某些場景性能更優(yōu) |
性能 | 在高并發(fā)且鎖競爭嚴重的場景下性能可能成為瓶頸 | 在同樣場景下可有更好的性能(但具體提升依賴于運行情況和 contention) |
可讀性/安全性 | 用 object ,可能誤用;不容易一眼看出這是鎖對象 | 用 Lock 類型,代碼語義直接告訴你“這是用來加鎖的” |
?? 總結(jié)
鎖是并發(fā)編程里的“雙刃劍”。
- 用得好 ?? 能保證線程安全,避免數(shù)據(jù)錯亂。
- 用不好 ?? 容易掉進性能陷阱,甚至導致死鎖,拖垮整個系統(tǒng)。
在 .NET 9 之前,我們習慣用 object
作為鎖對象,但語義模糊,容易被誤用。
而新的 System.Threading.Lock
專門為鎖而生,讓代碼更直觀,也在某些場景下帶來性能提升。
所以:
- 寫 demo、小項目 → 用
lock(object)
依舊沒問題。 - 寫業(yè)務(wù)、追求可維護性和性能 → 建議上手 .NET 9 的
Lock
,讓代碼更優(yōu)雅、更安全。
轉(zhuǎn)自https://www.cnblogs.com/ZYPLJ/p/19102575
該文章在 2025/10/10 10:15:46 編輯過