Этот шаблон блокировки ReaderWriterLockSlim выглядит правильно? - PullRequest
1 голос
/ 20 марта 2012

Я использую 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( ) ;
                }
            }
        }
    }

Ответы [ 2 ]

1 голос
/ 21 марта 2012

Выглядит нормально, но вам может понадобиться повторная блокировка для самого метода и, конечно, та, в которой вы итерируете свой список источников для получения блокировок.

0 голосов
/ 12 апреля 2013

Это старый вопрос, но я подумал, что было бы неплохо обновить его окончательным решением.Хотя у меня никогда не возникало проблем с вышесказанным, я применил разумную практику выхода из замков в обратном порядке, в котором они были приобретены.Таким образом, окончательный код выглядит примерно так:

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( ) ;
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...