我相信我至少已经很好地掌握了 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)是否有益?
最佳答案
多个线程不能构造同一个对象,也不应允许任何线程在完全构造之前使用该对象。因此,在理智的代码中,没有锁定的构造是安全的。
破坏是一个稍微难一点的案例。但同样,对对象进行适当的生命周期管理可以确保对象在某些线程可能仍在使用它时永远不会被销毁。
共享指针可以帮助实现这一点,例如。 :
- 在某个线程中构造对象
- 将共享指针传递给需要访问该对象的每个线程(如果需要,包括构造它的线程)
- 当所有线程都释放共享指针时对象将被销毁
但显然,还存在其他有效方法。关键是在对象生命周期的三个主要阶段之间保持适当的界限:构建、使用和销毁。绝不允许这些阶段中的任何一个重叠。
关于c++ - 在构造函数和析构函数中锁定共享资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11652748/