1

我一直在使用ReaderWriterLockSlim来同步读/写,到目前为止效果很好。

我有一组对象,读/写锁保存在Dictionary<string, ReaderWriterLockSlim>. 我有一个需要以原子方式获取多个读锁的场景。我确定我没有任何代码允许一个线程同时尝试持有多个写锁,这让我认为下面的代码可以毫无问题地工作。

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

假设以下情况,是否有人看到此代码有任何问题:

  1. 在其他地方,不允许持有写锁的线程持有任何其他锁(读或写)
  2. 多个线程可以同时持有任意数量的读锁

有什么想法吗?

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

2 回答 2

1

它看起来不错,但您可能需要在方法本身上设置重入锁,当然,还需要在其中迭代源列表以获取锁。

于 2012-03-21T08:31:31.607 回答
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( ) ;
            }
        }
    }
}
于 2013-04-12T13:40:32.850 回答