lock无竞争时开销极低(纳秒级),真正损耗在阻塞引发的上下文切换(几十微秒);推荐用Interlocked替代简单计数,读多写少场景优先用ReaderWriterLockSlim。

lock 的性能损耗在什么量级?
在无竞争(即几乎没线程抢锁)时,lock 的开销极低——现代 .NET(6+)会先自旋几轮,不进内核,耗时通常
典型对比(1000 万次计数操作,单核模拟竞争):
-
Interlocked.Increment(ref x):约 80–120 ms -
lock(obj) { x++; }:约 450–900 ms(取决于争抢强度) -
Mutex.WaitOne():常超 3000 ms(跨进程开销大)
什么时候该换 Interlocked 而不是 lock?
只要你的临界区只干一件事:读/写/更新一个字段(int、bool、引用等),且逻辑不依赖其他变量或状态判断,就该用 Interlocked。
常见误用场景:
- ❌
lock保护一个if (count > 0) count--;—— 这其实是「读-判-改」三步,lock正确但过重 - ✅ 改成
if (Interlocked.Decrement(ref count) >= 0) { /* 成功减了 */ }—— 原子 CAS,无锁,更快更安全 - ✅ 计数器、开关标志、引用替换(
Interlocked.Exchange)、初始化单例(Interlocked.CompareExchange)都适合
lock 真正的代价不在“加锁”,而在“阻塞”
lock 本身不慢,慢的是线程被迫挂起 + 唤醒带来的上下文切换。一个被阻塞的线程要经历:用户态 → 内核态 → 睡眠队列 → 调度唤醒 → 用户态,这过程至少耗费几十微秒,还吃 CPU 调度资源。
实操建议:
- 避免在
lock块里做 I/O、网络调用、Thread.Sleep、复杂计算——这些会让锁持有时间变长,放大争抢 - 不要用
string或装箱值类型(如(object)123)当锁对象——每次都是新对象,根本锁不住 - 优先用
private static readonly object _lock = new object();,别用this或 public 成员,防外部干扰
读多写少?别硬扛 lock,试试 ReaderWriterLockSlim
如果你的字段被读取几千次,只写几次(比如配置缓存、设备状态),lock 就是瓶颈:所有读操作也得排队。
换成 ReaderWriterLockSlim 后,读可以并发,写才互斥:
private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim(); private int _value;public int Value { get { _rwLock.EnterReadLock(); try { return _value; } finally { _rwLock.ExitReadLock(); } } set { _rwLock.EnterWriteLock(); try { _value = value; } finally { _rwLock.ExitWriteLock(); } } }
注意:它比 lock 略重(多一层状态管理),但读并发提升明显;若读写比例 Interlocked 或 volatile + 规则约束。
真正容易被忽略的一点:锁的粒度永远比锁的种类更重要。哪怕你用了 Interlocked,如果把它套在一个高频循环里反复调用,也比把几个相关字段打包进一个轻量 lock 块更慢——因为函数调用和内存屏障本身也有成本。









