C#中通过方法锁定属性访问的线程安全实现方案问询
解决方案
要实现你需要的事务式线程安全控制,ReaderWriterLockSlim是最适合的工具——它能区分读/写锁,既保证写操作(事务期间)的排他性,又能让无冲突的读操作并发执行,同时满足"更新事务完成后才允许读取"的需求。
修改后的完整类代码
internal class Invite : IDisposable { private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); private int _State = 0; public int State { get { // 读取时获取读锁,写锁持有期间会阻塞等待 _lock.EnterReadLock(); try { return _State; } finally { // 确保锁一定会释放,避免死锁 _lock.ExitReadLock(); } } set { // 如果允许直接修改State(不通过EnterUpdate),这里加写锁保证线程安全 // 若只允许在EnterUpdate事务内修改,可移除这段锁逻辑 _lock.EnterWriteLock(); try { _State = value; } finally { _lock.ExitWriteLock(); } } } public void EnterUpdate() { // 获取排他写锁,此时所有读/写操作都会阻塞 _lock.EnterWriteLock(); } public void ExitUpdate() { // 检查并释放写锁,避免重复释放引发异常 if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } } // 释放ReaderWriterLockSlim资源 public void Dispose() { _lock.Dispose(); } }
关键逻辑说明
读锁与写锁的排他性:
- 调用
EnterUpdate()后,当前线程会持有排他写锁,此时任何线程调用State的getter(读锁)或尝试获取写锁都会被阻塞,直到ExitUpdate()释放写锁。 - 无事务时,多个线程可以同时获取读锁读取
State,保证读性能。
- 调用
安全使用规范:
必须用try-finally包裹事务代码,确保锁在异常场景下也能释放:using var obInvite = new Invite(); try { obInvite.EnterUpdate(); // 执行第三方服务更新、修改State等操作 obInvite.State = await UpdateThirdPartyService(); } finally { obInvite.ExitUpdate(); }为什么之前的尝试可能失败:
- Mutex:是跨进程锁,开销极大,且若未正确调用
ReleaseMutex()会导致永久阻塞,不适合单进程内的线程同步。 - Monitor:仅支持排他锁,无法区分读/写场景,会导致所有读操作也串行执行,性能低下;若锁对象使用不当(比如用
this或值类型)也会引发问题。 - ReaderWriterLockSlim:若之前未正确配对
Enter/Exit锁(比如漏写finally释放),或错误混用读/写锁顺序,会导致死锁或锁不生效。
- Mutex:是跨进程锁,开销极大,且若未正确调用
内容的提问来源于stack exchange,提问作者bany365
相关产品推荐
相关产品推荐

