在使用课程时,我试图更好地理解std::mutex
,std::lock_guard
,std::unique_lock
。
对于初学者我有点了解lock_guard
和unique_lock
之间的区别:我知道lock_guard
只锁定构造上的互斥锁,这在类成员中使用时是首选用途功能如下:
class Foo {
std::mutex myMutex;
public:
void someFunc() {
std::lock_guard<std::mutex> guard( myMutex );
// code
}
};
如上所述,具有类成员myMutex的lock_guard将被锁定在函数Foo::someFunc()
范围的开头,然后在代码离开作用域后由于lock_guard
的析构函数而解锁和mutex
。
我也明白unique_lock
允许您锁定&amp;多次解锁互斥锁。
我的问题是关于设计课程的地方;如果我想将互斥锁锁定在类的构造函数中,那么当constructor
超出范围时不要解锁它,而是在调用类的析构函数时解锁...
class Foo {
std::mutex myMutex;
public:
Foo() {
// lock mutex here;
}
~Foo() {
// unlock mutex here;
}
};
可以实现上述目标;如果是这样的话?
在上面的最后一个例子中,我不确定的是:如果在类的构造函数中使用了lock_guard;它会在构造函数离开作用域之后超出作用域,还是在类的对象超出作用域时调用类的析构函数?我想尝试模仿所显示的第二个例子的期望行为。
答案 0 :(得分:0)
在我发布这个问题之后:我做了一些研究和一些试验和错误。有了这个,我选择了不同的实现和解决方案。
而不是我最初提出的建议,我最终使用了std::shared_mutex
和std:shared_lock
。
所以在我班级的标题中,我没有保存或存储任何mutex
。现在在我班级的cpp文件中。我正在使用静态全局shared_mutex
所以我的班级现在看起来像这样:
Foo.cpp
#include "Foo.h"
#include <mutex>
std::mutex g_mutex;
Foo::Foo() {
// code not locked
{ // scope of guard
std::lock_guard<std::mutex> lock( g_mutex );
// code to lock
} // end scope destroy guard unlock mutex
// other class code
}
Foo::someFunc() {
// Code to lock
std::lock_guard<std::mutex> lock( g_mutex );
}
我发现为什么它对我不起作用。在我的类的构造函数中,它从其父类或基类调用一个函数。然后父类或基类调用此类的静态成员,此类的静态成员函数也在同一个互斥锁上使用lock_guard。
我发现问题之后;我有两个选择。我可以使用2个独立的互斥锁,一个用于构造函数,一个用于静态方法。经过一番思考后我觉得如果我使用2,并且我阻塞了完整的构造函数,当前的锁和互斥锁将不会超出范围,直到类实例被销毁;然而,班级的生命几乎将是申请的整个生命周期。然后,如果我在静态方法中使用了第二个互斥锁和锁定保护程序,那么将另一个lock_guard包装在现有方法周围将是多余的。所以我得出的结论是,我需要为需要被互斥锁阻塞的代码创建一个范围块{ }
,以便在此部分超出范围后可以解锁,然后构造函数可以自由调用静态方法,它可以重用与现在免费相同的互斥锁。该类现在正在正常工作,它不会崩溃,也不会抛出异常。