C++ 在类中正确使用互斥锁、锁、唯一锁

C++ 在类中正确使用互斥锁、锁、唯一锁,c++,multithreading,locking,mutex,c++17,C++,Multithreading,Locking,Mutex,C++17,我试图在使用类时更好地理解std::mutex,std::lock\u guard,std::unique\u lock 首先,我知道lock\u-guard和unique\u-lock之间的区别:我知道lock\u-guard只在构造时锁定互斥锁,这是在类成员函数中使用它时的首选用法: class Foo { std::mutex myMutex; public: void someFunc() { std::lock_guard<std::mutex&

我试图在使用类时更好地理解
std::mutex
std::lock\u guard
std::unique\u lock

首先,我知道
lock\u-guard
unique\u-lock
之间的区别:我知道
lock\u-guard
只在构造时锁定互斥锁,这是在类成员函数中使用它时的首选用法:

class Foo {
    std::mutex myMutex;

public:
    void someFunc() {
        std::lock_guard<std::mutex> guard( myMutex );

        // code
    }
};
能否实现上述目标;如果是这样,怎么办


在上面的最后一个例子中,我不确定的是:如果在类的构造函数中使用了锁保护;构造函数离开作用域后,它会离开作用域吗?或者当类的对象离开作用域时调用类的析构函数时,它会离开作用域吗?我喜欢尝试模仿第二个示例的预期行为。

在我发布了这个问题之后:我做了更多的研究和一些尝试和错误。因此,我选择了不同的实现和解决方案

与我最初的建议不同,我最终使用了
std::shared_mutex
std:shared_lock

因此,在类的标题中,我没有保存或存储任何
互斥体。现在在我班的cpp文件中。我使用的是静态全局
共享\u互斥

所以我的课现在看起来像这样:

Foo.cpp

#包括“Foo.h”
#包括
std::mutex g_mutex;
Foo::Foo(){
//代码未锁定
{//保护范围
std::锁和保护锁(g\U互斥);
//要锁定的代码
}//结束作用域销毁保护解锁互斥锁
//其他类别代码
}
Foo::someFunc(){
//要锁定的代码
std::锁和保护锁(g\U互斥);
}
我发现了为什么它对我不起作用。在我的类的构造函数中,它从父类或基类调用函数。然后父类或基类调用该类的静态成员,该类的静态成员函数也在同一互斥锁上使用lock_guard


发现问题后,;我有两个选择。我可以使用两个独立的互斥体,一个专门用于构造函数,另一个专门用于静态方法。经过一番思考,如果我使用2,并且我正在阻止完整的构造函数,那么在类实例被销毁之前,当前的锁和互斥不会超出范围;然而,类的生命周期将几乎是应用程序的整个生命周期。然后,如果我在静态方法中使用了第二个互斥锁和锁保护,那么在现有的锁保护周围包装另一个锁保护将是多余的。因此,我得出结论,我需要为需要被互斥锁阻止的代码创建一个作用域块
{}
,以便在该部分超出作用域后可以解锁,然后构造函数可以自由调用静态方法,并且可以重用现在自由使用的相同互斥锁。该类现在工作正常,在不应该的情况下不会崩溃或抛出异常。

还有谁会尝试获取互斥锁?问题是,在
~Foo
之前,他们无法解锁它,并且在
~Foo
之后不久,所有锁都将失效。因此,您需要一些方法,让每个等待互斥体的人都可以与
Foo
通信,以确保他们已经完成了等待;这样一个系统将比您的
Foo
类复杂得多,它的语义将大量改变实现
Foo
的正确方式。如果没有用例,
Foo
就无法设计(只有在ctor和dtor中锁定的互斥锁就好像什么都没有发生一样),您可以拥有一个
lock\u guard
数据成员,在ctor mem初始值设定项列表中获取锁,它将在dtor中解锁,但正如雅克所说,很难想象这样一个类会有用。@Yakk是的,我开始掌握互斥锁、锁守卫等的用法。。。但最后在做了一点更多的研究和尝试后,发布了这个问题的错误;我采取了不同的方法。我可以在我自己的回答中详细说明。@Praetorian是的,我已经发现在我的课堂上正确使用互斥体,并通过适当的行为达到预期目的;你可以参考我贴出的答案。
class Foo {
    std::mutex myMutex;
public:
    Foo() {
        // lock mutex here;
    }

    ~Foo() {
        // unlock mutex here;
    }
};
#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 );
}