我被用来支持一些遗留代码,而且我看到一些让我在困惑中挠头的事情。在代码的某些部分,我看到一个类实例使用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的优点,因此当执行退出范围时锁会自动释放。这两种实施都有其他好处/缺点吗?
答案 0 :(得分:2)
关键部分仅对单个进程内的线程可见/可用。可以在多个进程中显示互斥锁(通常通过创建命名的互斥锁)。你上面所说的并不足以说明这是否是他们两者的原因,但这是一种可能性。
答案 1 :(得分:2)
通常,互斥锁可用于通过命名的互斥锁控制跨进程的线程访问,而关键部分仅用于在同一进程空间中同步线程访问。
这些类都没有真正获得RAII的好处而没有包装它们,因为在这种情况下你永远不需要显式调用锁或解锁。例如,使用boost mutex lock来获取这些伪代码......
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
没有可重入锁定,因此递归会导致问题。根据您的任务,您可能有机会远离Windows API上的MFC包装器,并实现自己的原子锁或使用像std::mutex
这样的boost或C ++ 0x功能。不仅是更好的实施,还提供跨平台支持。