【发布时间】:2012-07-25 15:02:52
【问题描述】:
我相信我至少掌握了 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)会有好处吗?
【问题讨论】:
-
当您说“类”在多个线程之间使用时,我假设您的意思是 TestClass 类型的对象可能会在多个线程中使用。在这种情况下,您仍然只创建一个对象,因此您不需要在构造函数中锁定。如果两个线程同时在构造函数中,它们将生成 2 个单独的对象。锁定对象构造更有意义,以确保(例如)在对象完成构造之前不使用 mValueTwo。析构函数似乎应该锁定,以确保数据在被销毁时不被访问。
-
@Rollie 是的,我的意思是该对象将被共享。所以,如果我创建:
-
@Rollie:在类被破坏时访问类是实例生命周期管理的一个错误 - 发生这种情况时程序已经损坏(如果它可以在破坏时访问,它也可能发生之后)。
-
@Rollie 抱歉,按 Enter 太快了。是的,我的意思是该对象将被共享。所以,如果我创建:`TestClass* testPointer = new TestClass(1.1); ` 然后在构造函数完全返回之前不会为 testPointer 分配地址,因此没有其他线程可以访问该对象。这是一个正确的总结吗?
-
@GeorgFritzsche:很好,我唯一担心的是——如果确实发生了,期望的行为是什么?我自己不是 100% 确定 - 我会假设非作用域锁会永久阻止其他线程的访问,并且可能会使一个细微的错误更容易追踪。有没有更优雅的方式来处理此类错误?布雷特,如果 testPointer 本身在多个线程之间共享,则您需要防止两者一起进入该块。如果 2 个线程尝试像这样构造 testPointer,它们将处理它们认为共享的 2 个独立对象。
标签: c++ multithreading