我有下面这段C++代码,其中我使用了临界区对象(Critical Section object):
EnterCriticalSection(&cs);
// code that may throw an exception
LeaveCriticalSection(&cs);
如何确保即使抛出异常,也可以调用
LeaveCriticalSection
函数?我有下面这段C++代码,其中我使用了临界区对象(Critical Section object):
EnterCriticalSection(&cs);
// code that may throw an exception
LeaveCriticalSection(&cs);
LeaveCriticalSection
函数?只需要编写一个使用析构函数进行清理的守卫:
struct Guard {
CriticalSection& cs;
Guard(CriticalSection& cs)
: cs(cs)
{
EnterCriticalSection(cs);
}
~Guard() {
LeaveCriticalSection(cs);
}
Guard(const Guard&) = delete;
Guard& operator = (const Guard&) = delete;
};
使用方法:
void f() {
Guard guard(cs);
...
}
使用RAII(资源获取即初始化)习语:
struct GuardCS {
GuardCS(CRITICAL_SECTION& p_cs) : cs(p_cs){
EnterCriticalSection(&cs);
}
~GuardCS() {
LeaveCriticalSection(&cs);
}
private:
// Protect against copying, remove: =delete on pre c++11 compilers
GuardCS(GuardCS const &) = delete;
GuardCS& operator =(GuardCS const &) = delete;
CRITICAL_SECTION& cs;
};
如果您恰巧使用MFC,那么有一些抽象这种东西的类:Ccriticalsection是否可用于生产环境?
"即使抛出异常,我该怎么确保调用LeaveCriticalSection函数?"
您可以编写一个类似于以下代码的小助手类:
class CsLocker {
public:
CsLocker(CriticalSection& cs)
: cs_(cs) {
EnterCriticalSection(&cs_);
}
~CsLocker() {
LeaveCriticalSection(&cs);
}
CsLocker(const CsLocker&) = delete;
CsLocker& operator=(const CsLocker&) = delete;
private:
CriticalSection& cs_;
};
CsLocker
,你就完了。 - Lightness Races in Orbit更新:关键节和互斥锁之间的一个区别是您可以在一个线程上多次锁定关键节,但对于简单的std :: mutex,这并不正确。如果需要锁定的递归行为,请使用std::recursive_mutex std::lock_guard<std::recursive_mutex>
更新2:关键节和互斥锁之间的详细差异在此处描述,性能比较在此处进行。
原因:尽可能使用标准定义的机制更好。如果你使用平台特定的东西,要进行包装。所以,如果你担心性能问题,请创建一个带有锁定/解锁方法的关键部分类(以满足BasicLocakable概念要求),并使用std::lock_guard<MyCriticalSection>
。Boost.ScopeExit
实现的简单方法。#include <boost/scope_exit.hpp>
...
EnterCriticalSection(&cs);
BOOST_SCOPE_EXIT(&cs) {
LeaveCriticalSection(&cs);
} BOOST_SCOPE_EXIT_END
// code that may throw an exception