Должны ли замки и мьютексы в C # использоваться вместе - PullRequest
8 голосов
/ 13 марта 2009

Не будет ли это излишним, и только один из них необходим? Я искал и нашел различные сообщения о взаимном исключении и блокировках в C # здесь и здесь .

Пример:
В нашем приложении у нас есть функция, которая раскручивает несколько потоков переподключения, и внутри этого потока мы используем Mutex и lock. Разве lock не заблокирует доступ к этому разделу кода и не помешает обновлению connect каким-либо другим потоком?

bool connect = false;
Mutex reconnectMutex = new Mutex(false, "Reconnect_" + key);

try
{
   lock(site)
   {
      if(site.ContainsKey(key))
      {
         siteInfo = (SiteInfo)site[key];
         if(reconnectMutex.WaitOne(100, true))
         {
            connect = true;
         }
      }
   }

   if (connect)
   { 
      // Process thread logic
   }
}
catch
{}

reconnectMutex.ReleaseMutex();

Подробнее:
Это в ASP.NET WebService, не работающем в веб-саду.

Ответы [ 4 ]

11 голосов
/ 13 марта 2009

Mutex (потому что у него есть имя) остановит любой процесс на той же машине, к которому он также обращается, тогда как блокировка остановит только другие потоки в том же процессе. Из этого примера кода я не вижу, зачем вам нужны оба вида блокировки. Кажется хорошей практикой удерживать простую блокировку в течение короткого периода времени, но тогда гораздо более тяжелый межпроцессный мьютекс блокируется на возможно более длительный (хотя и частично совпадающий) период! Было бы проще просто использовать мьютекс. И, возможно, выяснить, действительно ли необходима межпроцессная блокировка.

Кстати, catch {} - абсолютно неправильная вещь в этом сценарии. Вы должны использовать finally { /* release mutex */ }. Они очень разные. Улов будет поглощать гораздо больше видов исключений, чем следовало бы, а также заставит вложенные обработчики finally выполнять в ответ на исключения низкого уровня, такие как повреждение памяти, нарушение доступа и т. Д. Поэтому вместо:

try
{
    // something
}
catch
{}

// cleanup

Вы должны иметь:

try
{
    // something
}
finally
{
    // cleanup
}

И если есть конкретные исключения, из которых вы можете восстановиться, вы можете их перехватить:

try
{
    // something
}
catch (DatabaseConfigurationError x)
{
    // tell the user to configure the database properly
}
finally
{
    // cleanup
}
3 голосов
/ 13 марта 2009

«замок» - это, по сути, просто синтаксический сахар для Montor.Enter / Exit. Mutex - это многопроцессорная блокировка.

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

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

2 голосов
/ 13 марта 2009

Как уже отмечали другие, Mutex блокирует процессы, а локальная блокировка (Monitor) блокирует только те потоки, которые принадлежат текущему процессу. Однако ...

Код, который вы показали, содержит довольно серьезную ошибку. Похоже, что вы отпускаете Mutex безоговорочно в конце (т.е. reconnectMutex.ReleaseMutex()), но Mutex получается только в том случае, если site.ContainsKey() возвращает true.

Так что, если site.ContainsKey возвращает false, то при освобождении Mutex будет выбрасываться ApplicationException, поскольку вызывающий поток не владеет Mutex.

1 голос
/ 13 марта 2009

Вы не дали достаточно информации, чтобы действительно ответить на этот вопрос. Как уже говорилось в Earwicker, Mutex позволяет синхронизировать процессы. Таким образом, если у вас есть два экземпляра одного и того же приложения, вы можете сериализовать доступ. Вы можете сделать это, например, при использовании внешних ресурсов.

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

...