c# lock 和 Mutex 的区别和性能 lock和Mutex哪个好

来源:这里教程网 时间:2026-02-21 17:39:11 作者:

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); }
    }
}
<p>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
等线程安全集合封装的操作。加锁是手段,不是目的。

相关推荐