我一直被用来支持一些遗留代码,并且看到一些使我困惑的事情。在代码的某些部分中,我看到一个类实例使用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 documentation for synchronization之后,似乎CClassB正在实现所建议的方法,但是我不清楚CClassA使用的实现中存在什么危险。据我所知,这两种方法之间的唯一区别是CSingleLock具有RAII的优势,因此当执行退出作用域时,该锁将自动释放。两种实现方式都有其他优点/缺点吗?

最佳答案

通常,互斥锁可用于通过命名的互斥锁来控制跨进程的线程访问,而关键部分仅用于同步同一进程空间中的线程访问。

如果不包装它们,这两个类都不会真正获得RAII的好处,因为在这种情况下,您将不需要显式调用锁定或解锁。以使用增强互斥锁为例的伪代码示例为例...

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

  // ...

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

现在,我认为您应该避免使用CMutexCCritalSectionCSemaphoreCEvent,因为这些实现有些中断,或者至少不如其他可用库(如boost)。例如:
  • 在废弃的互斥锁之间确定超时是不可能的,因为实现仅检查返回值而不是原因。
  • 没有使用CSingleLock的重入锁,因此递归将导致问题。
  • 无法在进程
  • 之间创建命名事件

    根据您要执行的任务,您可能有机会脱离Windows API上的MFC包装器,并实现自己的原子锁,或者使用诸如boost或std::mutex之类的C++ 0x功能,它们不仅是更好的实现,而且还提供跨平台支持。

    09-10 23:18