锁定构造函数和析构函数中的共享资源
Locking shared resources in constructor and destructor
我相信我至少掌握了C++中多线程的基本知识,但我从来没有得到关于在构造函数或析构函数中围绕共享资源锁定互斥锁的明确答案。我觉得你应该把这两个地方都锁起来,但最近同事们不同意。假设以下类由多个线程访问:
class TestClass
{
public:
TestClass(const float input) :
mMutex(),
mValueOne(1),
mValueTwo("Text")
{
//**Does the mutex need to be locked here?
mValueTwo.Set(input);
mValueOne = mValueTwo.Get();
}
~TestClass()
{
//Lock Here?
}
int GetValueOne() const
{
Lock(mMutex);
return mValueOne;
}
void SetValueOne(const int value)
{
Lock(mMutex);
mValueOne = value;
}
CustomType GetValueTwo() const
{
Lock(mMutex);
return mValueOne;
}
void SetValueTwo(const CustomType type)
{
Lock(mMutex);
mValueTwo = type;
}
private:
Mutex mMutex;
int mValueOne;
CustomType mValueTwo;
};
当然,通过初始化列表,一切都应该是安全的,但是构造函数中的语句呢?在析构函数中,进行非作用域锁定而从不解锁(本质上只调用pthread_mutex_destroy)是否有益?
多个线程不能构造同一个对象,也不应允许任何线程在完全构造对象之前使用该对象。因此,在健全的代码中,没有锁定的构造是安全的。
破坏是一个稍微困难的情况。但是,对对象进行适当的生命周期管理可以确保在某些线程可能仍在使用某个对象时,该对象永远不会被破坏
共享指针可以帮助实现这一点,例如:
- 在某个线程中构造对象
- 将共享指针传递给每个需要访问对象的线程(如果需要,包括构造对象的线程)
- 当所有线程都释放了共享指针时,对象将被销毁
但显然,还存在其他有效的方法。关键是在物体生命周期的三个主要阶段之间保持适当的界限:建造、使用和破坏。绝不允许这些阶段之间有重叠。
它们不必被锁定在构造函数中,因为在这一点上,任何外部人员都可以访问该数据的唯一方法是从构造函数本身传递它们(或者执行一些未定义的行为,如调用虚拟方法)。
[编辑:删除了关于析构函数的部分,因为正如一条评论正确断言的那样,如果你试图从一个可能已经死了的对象访问资源,你会遇到更大的问题]
相关文章:
- 共享指针析构函数中的内存顺序
- 在共享指针的值中调用 std::swap 调用一堆构造函数和析构函数
- 两个单链列表共享同一个节点和析构函数两次删除相同的内存
- 析构函数在与 STL 的共享指针中调用两次
- 析构函数提供删除资源的"may be used uninitialized"
- Boost共享指针构造函数/析构函数
- c++在没有虚拟析构函数的多态性中共享ptr
- 锁定构造函数和析构函数中的共享资源
- C++对共享库中类的构造函数和析构函数的未定义引用错误
- 是否可以使用 std::shared_ptr 创建共享对象池,并在没有自定义析构函数的情况下创建weak_ptr
- C++析构函数删除共享内存
- 使用共享指针时是否需要设置析构函数方法
- 指向"raw"资源的指针是否应该在析构函数中归零?
- 用于清理资源的析构函数
- 多态性=资源泄漏中基类缺少虚拟析构函数
- 为什么这个显式析构函数会导致共享ptr中的内存损坏
- 在公共层次结构中的类之间共享析构函数
- 从析构函数传递到this的共享指针
- 未在dlclose上调用共享库中全局静态变量的析构函数
- 只能在析构函数中释放一次的资源的惯用移动构造器