这个ReaderWriterLockSlim锁定模式是否正确?

时间:2012-03-20 17:22:35

标签: c# thread-safety readerwriterlockslim

我一直在使用ReaderWriterLockSlim来同步读/写,到目前为止它已经运行得很好。

我有一组对象,读/写锁在Dictionary<string, ReaderWriterLockSlim>中维护。我有一个场景,我需要获取多个读锁 原子 。我确定我没有任何代码允许一个线程同时尝试持有多个写锁,这让我觉得下面的代码可以正常工作。

如果我使用写锁而不是读锁来尝试下面的方法,我几乎可以肯定我最终会遇到死锁,除非我能确保锁定始终以相同的顺序发生(在我的情况下我不能)。

有没有人看到此代码有任何问题,假设如下:

  1. 在其他地方,任何持有写锁的线程都不允许持有任何其他锁(读或写)
  2. 多个线程可以同时保存任意数量的读锁
  3. 有什么想法吗?

    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( ) ;
                    }
                }
            }
        }
    

2 个答案:

答案 0 :(得分:1)

它看起来不错,但您可能需要对方法本身进行重新锁定锁定,当然还有一个迭代源列表以获取锁定的方法。

答案 1 :(得分:0)

这是一个老问题,但我认为用最终解决方案更新它仍然是好事。虽然我从来没有遇到过上述问题,但我采用了谨慎的做法,即以相反的顺序退出锁。因此最终代码看起来像这样:

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( ) ;
            }
        }
    }
}