8

少なくとも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を呼び出すだけ)と便利ですか?

4

2 に答える 2

12

複数のスレッドが同じオブジェクトを構築することはできません。また、完全に構築される前に、どのスレッドもオブジェクトを使用することを許可されるべきではありません。したがって、正常なコードでは、ロックなしの構築は安全です。

破壊は少し難しいケースです。ただし、オブジェクトを適切にライフタイム管理することで、一部のスレッドが引き続きオブジェクトを使用する可能性がある場合に、オブジェクトが破棄されないようにすることができます。

共有ポインタは、これを達成するのに役立ちます。:

  • 特定のスレッドでオブジェクトを構築します
  • オブジェクトへのアクセスが必要なすべてのスレッド(必要に応じてオブジェクトを構築したスレッドを含む)に共有ポインターを渡します
  • すべてのスレッドが共有ポインタを解放すると、オブジェクトは破棄されます

しかし、明らかに、他の有効なアプローチが存在します。重要なのは、オブジェクトの存続期間の3つの主要な段階(構築、使用、破壊)の間に適切な境界を維持することです。これらのステージのいずれかの間でオーバーラップを許可しないでください。

于 2012-07-25T15:13:23.173 に答える
1

外部の誰もがその時点でそのデータにアクセスできる唯一の方法は、コンストラクター自体からデータを渡す(または仮想メソッドの呼び出しなどの未定義の動作を行う)場合であるため、コンストラクターでロックする必要はありません。 。

[編集:コメントが正しく主張しているように、死んでいる可能性のあるオブジェクトからリソースにアクセスしようとすると、より大きな問題が発生するため、デストラクタに関する部分を削除しました]

于 2012-07-25T15:13:35.023 に答える