2010-02-10 2 views
3

Это теоретический вопрос; У меня нет реальной проблемы для решения, я просто хочу понять, как это работает.Почему программа ReaderWriterLock не запускается автоматически при закрытии потока пользователей?

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

Вот тестовый пример, демонстрирующий проблему.

static void Main(string[] args) 
    { 
     ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim(); 

     Thread t1 = new Thread((a) => 
     { 
      readerWriterLock.EnterReadLock(); 

      // this thread omits to Exit the lock.... 
     }); 

     Thread t2 = new Thread((a) => 
     { 
      readerWriterLock.EnterWriteLock(); 
     }); 

     t1.Start(); 
     t2.Start(); 

     // wait for all threads to finish 
     t1.Join(); 
     t2.Join(); 
    } 

ответ

3

Простого ответ: Там нет простого способа автора нить знает, что читатель тема окончилась, без того, что делает блокирующие операции дорого.

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

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

+0

В контексте потока, который разбился, я согласен, что предполагая, что ресурс, который он заблокировал, теперь находится в чистом состоянии, был бы рискован. Но в контексте нормального завершения потока я считаю, что такое предположение было бы безопасным. Что касается производительности, они могут обеспечить две реализации: тот, который у нас есть сейчас, и более медленный, но более умный, который реализует автоматический выпуск. Во всяком случае, благодарю вас за ваш ответ, я думаю, что вы объяснили, действительно, причина, почему это делается именно так. – Sylvain

+1

Re: нормальное завершение потока, вы можете рассмотреть использование шаблона RAII для блокировок, что поможет обеспечить освобождение блокировки при выходе из некоторой области. В C# вы можете использовать ключевое слово _lock_ (для обычных блокировок) или _try/finally_ блоков (для вашего ReaderWriterLock), чтобы обеспечить освобождение блокировок при выходе из области действия. Опять же, это не поможет вам, если поток потерпел крушение, или если он вызвал функцию нисходящего выхода более низкого уровня, но это поможет снизить риск блокировок от ошибок программирования, когда вы забудете освободить блокировку на некотором запутанном пути кода , – 0xfe

0

Вероятно, для блокировки не было бы слишком сложно сохранить идентификатор потока, который содержит его исключительно, или список потоков, которые хранят его не исключительно. Затем код блокировки может периодически проверяться, пока он заблокирован, чтобы убедиться, что все или все потоки, которые его блокируют, все еще живы. Самая большая проблема с этим заключается в том, что нет стандартных способов для потоков указывать, в какие моменты сущности, защищенные блокировкой, находятся в законном состоянии или недействительны. Если поток, который удерживает блокировку, умирает, когда защищенные объекты находятся в недействительном состоянии, доступ к этим объектам должен оставаться запрещенным до тех пор, пока какой-либо код, который знает, как бороться с коррупцией, сделал это.

Смежные вопросы