锁定构造函数和析构函数中的共享资源

Bre*_*ett 7 c++ multithreading

我相信我已经很好地处理了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;
};
Run Code Online (Sandbox Code Playgroud)

当然,通过初始化列表,一切都应该是安全的,但构造函数中的语句呢?在析构函数中,执行非作用域锁定是有益的,并且永远不会解锁(基本上只是调用pthread_mutex_destroy)?

San*_*ker 12

多个线程不能构造相同的对象,也不允许任何线程在完全构造之前使用该对象.因此,在合理的代码中,没有锁定的构造是安全的.

毁灭是一个稍微困难的案例.但同样,对象的适当生命周期管理可以确保在某些线程可能仍然使用它时,永远不会销毁对象.

共享指针可以帮助实现这一点,例如.:

  • 在某个线程中构造对象
  • 将共享指针传递给需要访问该对象的每个线程(包括构造它的线程,如果需要)
  • 当所有线程释放共享指针时,该对象将被销毁

但显然,存在其他有效方法.关键是要在对象的生命周期的三个主要阶段之间保持适当的界限:构造,使用和破坏.绝不允许任何这些阶段之间的重叠.

  • 我必须把它拿回来.shared_ptr上的减量是原子的,因此如果没有调用线程首先穿过障碍,就不可能调用析构函数.我很抱歉. (5认同)