lock是纯托管同步原语,仅限同一进程内线程间使用;Mutex是内核对象,支持跨进程同步但每次调用引发用户态/内核态切换,性能相差一个数量级。

lock 和 Mutex 的本质区别在哪?
lock 是 C# 关键字,底层直接调用 Monitor.Enter 和 Monitor.Exit,纯托管、无系统调用;Mutex 是 Windows 内核对象(.NET 封装),每次 WaitOne / ReleaseMutex 都会触发用户态 → 内核态切换。这意味着:
• lock 只能在**同一进程内**的线程间同步
• Mutex 可跨进程、跨 AppDomain,甚至能被其他语言(如 C++)创建的进程识别
性能差距有多大?实际测出来才信
在单进程多线程场景下,lock 比 Mutex 快一个数量级。实测(0xFFFFF ≈ 1048575 次临界区进入):
• lock:约 1335 ms
• Mutex:通常在 10000+ ms 量级(取决于系统负载)
原因不是“Mutex 写得差”,而是每次等待都得进内核——哪怕锁立刻可用,也要走一遍上下文切换开销。
private void TestWithLock(int times)
{
for (int i = 0; i < times; i++)
{
lock (_lockObj) { Acc(i); }
}
}
private void TestWithMutex(int times)
{
for (int i = 0; i < times; i++)
{
_mutex.WaitOne(); // 这里就已进内核
try { Acc(i); }
finally { _mutex.ReleaseMutex(); }
}
}
什么时候非用 Mutex 不可?
只有当你要解决**跨进程竞争**时才需要 Mutex,例如:
• 多个独立 EXE 程序共用同一个本地数据库文件(需确保写入互斥)
• Windows 服务 + 桌面客户端共享配置缓存文件
• 单实例应用(通过命名 Mutex 检测是否已有进程运行)
其他所有情况——包括 ASP.NET 请求处理、后台任务队列、内存缓存更新——都该用 lock 或 Monitor。
- 别用
lock(this)或lock(typeof(MyClass)):容易引发外部死锁 - 别把
int、string当锁对象:string有字符串驻留,int会装箱成不同对象,导致锁失效 -
Mutex创建时若传入名称(如new Mutex(false, "MyApp.GlobalLock")),它就变成全局内核对象,必须注意权限和释放——忘了ReleaseMutex会导致其他进程永久阻塞
Monitor 能不能替代 Mutex?
不能。Monitor 和 lock 一样,只作用于当前进程内的线程;它比 lock 多出 TryEnter(可设超时防死锁)、Wait/Pulse(线程协作),但依然**不跨进程**。如果你只是想避免 lock 无法超时的问题,用 Monitor.TryEnter(obj, timeout) 即可,无需升格到 Mutex。
真正该警惕的,不是“选错锁”,而是“根本不需要锁”——比如只读静态数据、每个线程独享的局部变量、或已被 ConcurrentDictionary 等线程安全集合封装的操作。加锁是手段,不是目的。











