我正在使用c ++进行win 32多线程处理。 场景: 我有一个多线程使用的函数。 此函数作为关键部分(或任何可以锁定资源的构造)。 在临界区中抛出异常。 此时我需要在异常catch块中解锁资源。
还有其他方法可以做到吗?我的意思是,让我们说我不想记得在catch块中释放锁,是否有任何常见的方法来处理这个问题以避免这种容易出错的情况?
答案 0 :(得分:16)
这个想法是封装获取和释放对象中的关键部分的行为,以便构造对象获取CS并销毁对象释放它。
struct CSHolder {
explicit CSHolder(CRITICAL_SECTION& cs): lock(cs) {
::EnterCriticalSection(&lock);
}
~CSHolder() { ::LeaveCriticalSection(&lock); }
CRITICAL_SECTION& lock;
};
CRITICAL_SECTION gLock;
void foo() {
CSHolder lockIt(gLock);
// lock is held until lockIt is destroyed
}
这个概念叫做RAII - 资源获取是初始化。这是现代C ++中非常常见的习语。
答案 1 :(得分:3)
如果您正在使用现有框架,那么您可能已经拥有可以为您执行此操作的RAII容器类。如果您使用的是MFC,请查看CSingleLock
,如果您正在使用scoped_lock
的加速查看。
令人遗憾的是,每个人似乎都必须(或者认为必须)自己动手。
答案 2 :(得分:2)
编写一个括号类,它将一个临界区作为构造函数参数。在构造函数中调用EnterCriticalSection,在析构函数中调用LeaveCriticalSection。如果抛出C ++异常,堆栈展开将完成剩下的工作。
答案 3 :(得分:2)
如果您可以使用MFC,则可以使用CSingleLock执行此操作。您可以像这样使用它:
void f()
{
try
{
CSingleLock lock(&m_criticalSection, TRUE);
}
catch(/*some exception*/)
}
锁将负责解锁其析构函数中的关键部分。因为lock是抛出异常时的本地对象,所以堆栈展开并执行锁定对象析构函数来解锁你的关键部分。