6

我被指派支持一些遗留代码,我看到一些让我困惑地挠头的事情。在某些代码段中,我看到一个类实例使用 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 的好处,所以当执行退出作用域时,锁会自动释放。这两种实施方式是否还有其他优点/缺点?

4

2 回答 2

2

关键部分仅对单个进程内的线程可见/可用。可以在多个进程中使互斥锁可见(通常通过创建命名互斥锁)。您上面显示的内容不足以说明这是否是他们两者兼有的原因,但这是一种可能性。

于 2011-05-19T18:27:01.883 回答
2

一般来说,互斥锁可用于通过命名互斥锁控制跨进程的线程访问,而临界区仅用于同步同一进程空间中的线程访问。

如果不包装它们,这些类都不能真正获得 RAII 的好处,因为在这种情况下,您永远不需要显式调用 lock 或 unlock。以使用 boost 互斥锁的这一点伪代码为例...

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没有使用so 递归的可重入锁会导致问题。
  • 无法在进程之间有命名事件

根据您的任务,您可能有机会摆脱 Windows API 上的 MFC 包装器并实现自己的原子锁或使用诸如 boost 或 C++0x 之类的功能std::mutex,这些功能不仅是更好的实现,而且提供交叉-平台支持。

于 2011-05-23T17:54:28.657 回答