ReaderWriterLock 已过时,应改用 ReaderWriterLockSlim;前者基于内核对象、开销大、无超时返回机制、不支持锁升级,后者为用户态高性能实现,支持超时、升级/降级、严格配对释放及递归策略控制。
ReaderWriterLock 在 .NET Framework 2.0 中引入,但自 .NET Framework 3.5 起就被官方弃用;它未被包含在 .NET Core / .NET 5+ 的默认 API 集中,且在 netstandard2.0 及更高版本中仅作为兼容性类型存在(需引用 System.Threading 程序集)。微软文档和源码注释中均标注其“obsolete”,不建议新项目使用。
CreateEvent),开销大、响应慢、易死锁TryEnterReadLock(int) 等方法,超时失败时抛出 ApplicationException,而非返回 false,难以安全捕获和处理ReaderWriterLockSlim 是 .NET Framework 3.5 引入的托管替代方案,专为高性能、低开销、高可控性设计。它完全在用户态实现(无内核切换),支持完整的超时控制、升级/降级语义,并被深度集成进 .NET Core / .NET 5+ 的基础类库中。
Try 版本:TryEnterReadLock(int)、TryEnterWriteLock(int)、TryEnterUpgradeableReadLock(int),失败直接返回 false,避免异常干扰流程EnterUpgradeableReadLock() → EnterWriteLock() 升级路径(注意:必须在同一线程内完成,且不能嵌套或跨 await)LockRecursionPolicy(默认 NoRecursion),显式禁止递归加锁,提前暴露线程安全漏洞ExitReadLock() / ExitWriteLock() / ExitUpgradeableReadLock(),否则会引发 SynchronizationLockException
很多人照搬 lock 的写法,只在写操作加锁、读操作裸奔——这在 ReaderWriterLockSlim 下是严重错误,会导致脏读或 KeyNotFoundException(尤其在 Dictionary 上)。
EnterReadLock(),写走 EnterWriteLock(),升级写走 EnterUpgradeableReadLock() + EnterWriteLock()
ExitXxxLock() 或在异常路径中遗漏释放,将导致锁永久占用,后续线程无限等待(表现为 CPU 低但请求卡死)async 方法中持有 ReaderWriterLockSlim 锁——它**不是 await 安全的**。若需异步等待,请改用 AsyncReaderWriterLock(如 Nito.AsyncEx 提供)ReaderWriterLockSlim 的优势只在「读远多于写」且「单次读操作耗时明显」时才显著。若读操作极轻(如简单字段访问)、或并发度不高(lock 反而更高效、更简洁。
ReaderWr
iterLockSlim 性能可能低于 Monitor(即 lock)ConcurrentDictionary、ConcurrentQueue),优先用它们,比手写锁更可靠、更免维护ReaderWriterLockSlim,并确保锁粒度合理(宁拆勿合)private static readonly Dictionary升级锁、跨线程释放、混用 async/await —— 这些地方不报错,但会在某个高并发时刻突然崩掉,而且很难复现。别等线上报警才查。_cache = new(); private static readonly ReaderWriterLockSlim _rwLock = new(LockRecursionPolicy.NoRecursion); public static bool TryGetValue(string key, out double value) { _rwLock.EnterReadLock(); try { return _cache.TryGetValue(key, out value); } finally { _rwLock.ExitReadLock(); } } public static void SetValue(string key, double value) { _rwLock.EnterWriteLock(); try { _cache[key] = value; } finally { _rwLock.ExitWriteLock(); } }