Проблемы .NET ReaderWriterLockSlim

В классе ReaderWriterLockSlim написано много статей, которые позволяют многократно читать и писать. Все из них (по крайней мере, что я нашел) рассказывают, как использовать его без особого объяснения, почему и как это работает. Стандартный пример кода:

lock.EnterUpgradeableReadLock();

try
{
   if (test if write is required)
   {
      lock.EnterWriteLock();

      try
      {
          change the resourse here.
      }
      finally
      {
         lock.ExitWriteLock();
      }
   }
}
finally
{
   lock.ExitUpgradeableReadLock();
}

Возникает вопрос: если обновляемая блокировка разрешает только один поток вводить его раздел, почему я должен вызвать метод EnterWriteLock внутри? Что произойдет, если я этого не сделаю? Или что произойдет, если вместо EnterUpgradeableReadLock я вызову EnterWriteLock и напишу на ресурс без использования возможности обновления блокировки вообще?

Ответ 1

Поверхность использования EnterUpgradeableReadLock over EnterReadLock заключается в том, что вы можете точно знать, что условие, которое вы проверяете, чтобы определить, следует ли вводить блокировку записи или нет, не изменяется между проверкой состояния и фактическим вводом напишите блокировку. Это позволяет избежать дублирования, которое может потребоваться с помощью регулярных lock s:

if (whatever-condition)
{
    lock (_lockObject)
    {
        // the condition may have changed betwen the check and the lock; verify
        // that the condition is still valid
        if (whatever-condition)
        {
            // do the stuff
        }
    }
}

В то же время он не блокирует вызовы EnterReadLock, поэтому другие потоки могут по-прежнему получать доступ на чтение в других частях кода (и эти вызовы, конечно, блокируют вызов до EnterWriteLock, пока они не отпустите блокировки чтения).

Ответ 2

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

EnterWriteLock будет блокировать другие потоки, которые нужно читать только - если вы используете обновляемую блокировку, другие потоки все равно могут получить блокировки чтения. Из EnterUpgradableLock документация:

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

Ответ 3

Класс ReaderWriterLockSlim по существу обертывает блокировку записи и позволяет всем читателям читать, пока блокировка записи не удерживается. После блокировки записи считыватели не могут читать.

Идея EnterUpgradeableReadLock заключается в том, чтобы позволить программисту явно указать свое намерение и не случайно модифицировать материал.

pm100 - это быстрее, потому что блокировка не является эксклюзивной, так как многие потоки могут читать сразу, что может ускорить чтение тяжелых приложений. На самом деле, если ваше приложение написано тяжелым, это может оказаться не лучшим решением для вас. Это лучше всего работает, когда модификации редко выполняются, но требуется много чтений.