CMutex :: Lock против CSingleLock :: Lock - PullRequest
5 голосов
/ 19 мая 2011

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

class CClassA : public CObject
{
public:
   void DoSomething();

private:
   CMutex m_mutex;
}

void CClassA::DoSomething()
{
   m_mutex.Lock();

   //...logic...

   m_mutex.Unlock();
}

В другом месте того же проекта я обнаружил, что код использует CSingleLock

class CClassB : public CObject
{
public:
   void DoSomething();

private:
   CCriticalSection m_crit;
}

void CClassB::DoSomething()
{
   CSingleLock lock(&m_crit);
   lock.Lock();

   //...logic...

   lock.Unlock();
}

После просмотра документации MSDN для синхронизации может показаться, что CClassB реализует рекомендованный метод, но мне не ясно, какова опасность в реализации, используемой CClassA. Насколько я могу судить, единственное различие между этими двумя методами состоит в том, что CSingleLock имеет преимущество RAII, поэтому блокировка автоматически снимается, когда выполнение выходит из области действия. Есть ли какие-либо другие преимущества / недостатки у какой-либо реализации?

Ответы [ 2 ]

2 голосов
/ 23 мая 2011

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

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

void DoSomething()
{
  // construction acquires lock on mutex
  boost::scoped_lock lock(&aBoostMutex);

  // ...

} // end scope - object is destroyed and lock is released

Теперь я бы сказал, что вам следует избегать CMutex, CCritalSection, CSemaphore и CEvent, потому что реализации несколько сломаны или, по крайней мере, уступают другим доступным библиотекам, таким как boost. Например:

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

В зависимости от того, что вам поручено, у вас может быть возможность отойти от оболочек MFC в Windows API и реализовать собственные атомарные блокировки или использовать что-то вроде boost или C ++ 0x, например std::mutex, которые не только являются лучшими реализациями, но обеспечивают кроссплатформенную поддержку.

2 голосов
/ 19 мая 2011

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

...