C#怎么实现读写锁 ReaderWriterLockSlim使用教程

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

ReaderWriterLockSlim 是 C# 中高效、轻量的读写锁实现,适合“多读少写”场景,能显著提升并发性能。它比传统的

lock
Monitor
更灵活,允许多个线程同时读,但写操作独占,且支持超时、取消和递归控制(可禁用)。

基本用法:读锁与写锁的正确加解锁

必须成对调用

EnterReadLock
/
ExitReadLock
EnterWriteLock
/
ExitWriteLock
,推荐用
try/finally
保证释放,避免死锁。

读操作:多个线程可同时进入,调用
EnterReadLock()
→ 访问共享资源 → 必须
ExitReadLock()
写操作:互斥独占,调用
EnterWriteLock()
→ 修改共享资源 → 必须
ExitWriteLock()
不要混用:不能在持有读锁时直接升级为写锁(会死锁),需先释放读锁再申请写锁

安全写法示例:带超时和异常防护

实际项目中建议启用超时机制,防止无限等待;并始终在

finally
块中释放锁:

private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
<p>public string GetData()
{
_rwLock.EnterReadLock();
try
{
return _sharedData;
}
finally
{
_rwLock.ExitReadLock();
}
}</p><p>public void UpdateData(string value)
{
if (_rwLock.TryEnterWriteLock(1000)) // 等待1秒,超时返回false
{
try
{
_sharedData = value;
}
finally
{
_rwLock.ExitWriteLock();
}
}
else
{
throw new TimeoutException("获取写锁超时");
}
}

进阶控制:禁用递归、设置公平模式、响应取消

ReaderWriterLockSlim
构造时可传入参数调整行为:

禁用递归:
new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion)
,避免同一线程重复加锁导致逻辑混乱
启用公平模式:
new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion, LockRecursionPolicy.NoRecursion)
(注意:.NET 6+ 支持
new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion) { UseSpinWait = false }
配合公平队列,但真正公平需手动管理)——更准确地说,它本身不提供严格公平,但可通过
TryEnter*
+ 重试 + 取消令牌模拟
配合
CancellationToken
:使用
TryEnterReadLock(Int32, CancellationToken)
等重载,实现可取消的等待

注意事项与常见坑

几个容易忽略却关键的细节:

务必调用
Dispose()
释放底层内核资源(尤其长期存活对象),建议封装为
IDisposable
类型或在
using
中创建(但注意:它不是设计为短生命周期对象,通常作为字段长期持有)
不要在锁内调用未知外部方法(如事件、虚方法、LINQ 查询),可能引发死锁或延长锁持有时间 读锁下禁止修改被保护的数据,否则破坏线程安全;写锁是唯一允许修改的时机 嵌套锁顺序要一致(如先读再写,所有线程都按此顺序),否则易引发死锁

基本上就这些。用好

ReaderWriterLockSlim
的关键是理解“读共享、写独占”的模型,配合适当的超时和异常防护,就能在高并发读场景下兼顾安全与性能。

相关推荐