CMutex::Lock vs. CSingleLock::Lock

CMutex::Lock vs. CSingleLock::Lock

本文关键字:Lock CSingleLock vs CMutex      更新时间:2023-10-16

我被挖掘支持一些遗留代码,我看到一些让我困惑地挠头的事情。 在某些代码部分中,我看到类实例使用 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的优点,因此当执行退出范围时,锁会自动释放。 这两种实现还有其他优点/缺点吗?

通常,

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

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

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或C++0x功能,如std::mutex,这不仅是更好的实现,而且提供跨平台支持。

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