这个ReaderWriterLockSlim锁定模式看起来正确吗
本文关键字:看起来 模式 ReaderWriterLockSlim 锁定 这个 | 更新日期: 2023-09-27 18:28:29
我一直在使用ReaderWriterLockSlim来同步读/写,到目前为止它运行得很好。
我有一个对象集合,读/写锁在Dictionary<string, ReaderWriterLockSlim>
中维护。我有一个场景,需要以原子方式获取多个读锁。我确信我没有任何代码可以允许一个线程同时持有多个写锁,这让我认为下面的代码可以毫无问题地工作。
如果我用写锁而不是读锁来尝试下面的方法,我几乎可以肯定我最终会出现死锁,除非我能确保锁定总是以相同的顺序发生(在我的情况下我不能这样做)。
有人看到这个代码有任何问题吗?假设如下:
- 在其他地方,不允许持有写锁的线程持有任何其他锁(读或写)
- 多个线程可以同时持有任意数量的读锁
有什么想法吗?
public void WithReaderLocksForItemsNamed(string[] itemNames, Action action)
{
// this gets locks for the items specified from my internation dictionary
ReaderWriterLockSlim[ ] locks = LocksForItemsNamed( itemNames ) ;
try
{
foreach( var @lock in locks )
{
@lock.EnterReadLock( ) ;
}
action( ) ;
}
finally
{
foreach( var @lock in locks )
{
if (@lock.IsReadLockHeld)
{
@lock.ExitReadLock( ) ;
}
}
}
}
看起来不错,但您可能需要在方法本身上使用可重入锁,当然,还需要迭代源列表以获得锁。
这是一个老问题,但我认为用最终解决方案更新它仍然很好。尽管我从未遇到过上述问题,但我采用了谨慎的做法,即以获取锁的相反顺序退出锁。因此,最终的代码看起来像这样:
public void WithReaderLocksForItemsNamed(string[] itemNames, Action action)
{
// this gets locks for the items specified from my internation dictionary
ReaderWriterLockSlim[ ] locks = LocksForItemsNamed( itemNames ) ;
try
{
foreach( var @lock in locks )
{
@lock.EnterReadLock( ) ;
}
action( ) ;
}
finally
{
foreach( var @lock in locks.Reverse() )
{
if (@lock.IsReadLockHeld)
{
@lock.ExitReadLock( ) ;
}
}
}
}