gpt4 book ai didi

c++ - 在类中正确使用 mutex、lock_guard、unique_lock

转载 作者:行者123 更新时间:2023-12-03 12:48:33 31 4
gpt4 key购买 nike

在使用类时,我试图更好地理解 std::mutexstd::lock_guardstd::unique_lock .

对于初学者来说,我知道 lock_guardunique_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_guardmutex 的析构函数。

我还了解 unique_lock 允许您多次锁定和解锁互斥锁。

我的问题是关于类的设计;如果我希望互斥体被锁定在类的构造函数中,那么当构造函数超出范围时不要将其解锁,而是在调用类的析构函数时解锁。 .

class Foo {
std::mutex myMutex;
public:
Foo() {
// lock mutex here;
}

~Foo() {
// unlock mutex here;
}
};

以上能否实现;如果是的话怎么办?

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

最佳答案

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

我最终使用了 std::shared_mutexstd:shared_lock,而不是我最初提议的。

因此,在我的类的 header 中,我没有保存或存储任何互斥体。现在在我类(class)的 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 将是多余的。所以我得出的结论是,我需要为需要被互斥体阻塞的代码创建一个作用域 block { } ,以便在该部分超出作用域后可以解锁,然后构造函数可以自由调用静态方法,并且可以重用与现在相同的互斥锁。该类现在可以正常工作,并且不会崩溃,也不会抛出不应发生的异常。

关于c++ - 在类中正确使用 mutex、lock_guard、unique_lock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49636732/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com