提问人:leuction 提问时间:5/13/2022 最后编辑:leuction 更新时间:5/14/2022 访问量:238
在 ExitWriterLock 之后释放 ReaderWriterLockSlim
Dispose ReaderWriterLockSlim after ExitWriterLock
问:
我有一个清理一些对象以及 ReaderWriterLockSlim 的功能。但是我需要 ReaderWriterLockSlim 锁定为写入器锁,以防止另一个线程在我进行清理时读取数据。
ConcurrentDictionary<string, ReaderWriterLockSlim> RwLocks = new ConcurrentDictionary<string, ReaderWriterLockSlim>();
private ReaderWriterLockSlim GetRwLock(string key)
{
return RwLocks.GetOrAdd(key, _ => new ReaderWriterLockSlim());
}
public void CleanUp(string key)
{
ReaderWriterLockSlim rwLock = this.GetRwLock(key);
try
{
rwLock.EnterWriterLock();
// do some other clean up
this.RwLocks.TryRemove(key, out _);
}
finally
{
rwLock.ExitWriterLock();
// It is safe to do dispose here?
// could other thread enter the read lock or writer lock here?
// and the dispose will throw exceptions?
// What is the best practice to do the dispose?
rwLock.Dispose();
}
}
我有一个想法来包装.你认为它可以解决问题还是有任何潜在风险ReaderWriterLockSlim
public class ReaderWriterLockSlimWrapper
{
private ReaderWriterLockSlim rwLock;
private volatile bool disposed;
public ReaderWriterLockSlimWrapper()
{
rwLock = new ReaderWriterLockSlim();
disposed = false;
}
private void DisposeInternal()
{
if (!rwLock.IsReadLockHeld && !rwLock.IsUpgradeableReadLockHeld && !rwLock.IsWriteLockHeld)
{
rwLock.Dispose();
}
}
public void Dispose()
{
disposed = true;
DisposeInternal();
}
public void EnterReadLock()
{
rwLock.EnterReadLock();
}
public void ExitReadLock()
{
rwLock.ExitReadLock();
if (disposed)
{
DisposeInternal();
}
}
public void EnterWriteLock()
{
rwLock.EnterWriteLock();
}
public void ExitWriteLock()
{
rwLock.ExitWriteLock();
if (disposed)
{
DisposeInternal();
}
}
}
答:
0赞
Theodor Zoulias
5/14/2022
#1
您尚未描述打算使用两种机制的具体方案,无论是第一种机制还是 / 方法,第二种机制都是类。所以我想问题是:CleanUp
GetRwLock
ReaderWriterLockSlimWrapper
我的两种机制是否可以在所有可能的多线程方案中安全使用,其中线程安全和操作原子性是强制性的?
答案是否定的,你们的两种机制都充斥着竞争条件,并且不能保证原子性。在多线程方案中使用它们会导致未定义的行为,包括但不限于:
- 意外的异常。
- 违反正确使用的
ReaderWriterLockSlim
通常应强制执行的策略。换句话说,两个线程可能会同时获取同一密钥的写入器锁,或者与已获取同一密钥的读取器锁的其他线程同时获取,或两者兼而有之。
解释为什么你的机制是有缺陷的,这是相当复杂的。一般的解释是,每当您在多线程环境中使用该模式时,尽管 和 可能是单独的线程安全的,但您允许第二个线程在两个调用之间抢占当前线程,并使第一个检查的结果无效。if (x.BooleanProperty) x.Method();
BooleanProperty
Method
顺便说一句,请注意 不是跨进程同步原语。因此,即使您修复了机制,然后尝试在 Web 应用程序中使用它们,这些策略仍可能被违反,因为 Web 服务器可能会在随机时刻决定回收当前进程并启动新进程。在这种情况下,Web 应用程序可能会在两个进程上同时运行,运行时间跨度为几秒钟甚至几分钟。ReaderWriterLockSlim
评论
ReaderWriterLockSlim
CleanUp