2017-06-14 33 views
2

unique_ptrをマルチスレッドで使用することについていくつかの心配があります。mutexはありません。私は以下の簡単なコードを書きました。見てください。 unique_ptr != nullptrをチェックすると、スレッドセーフなのでしょうか?マルチスレッドでのunique_ptr

class BigClassCreatedOnce 
{ 
public: 
    std::atomic<bool> var; 

    // A lot of other stuff 
}; 

BigClassCreatedOnceクラスのインスタンスは一度だけ作成されますが、私は、スレッド間でそれを使用することが安全であるかわかりません。

class MainClass 
{ 
public: 
    // m_bigClass used all around the class from the Main Thread 

    MainClass() 
     : m_bigClass() 
     , m_thread() 
    { 
     m_thread = std::thread([this]() { 
      while (1) 
      { 
       methodToBeCalledFromThread(); 
       std::this_thread::sleep_for(std::chrono::milliseconds(1)); 
      } 
     }); 

     // other stuff here 

     m_bigClass.reset(new BigClassCreatedOnce()); // created only once 
    } 

    void methodToBeCalledFromThread() 
    { 
     if (!m_bigClass) // As I understand this is not safe 
     { 
      return; 
     } 

     if (m_bigClass->var.load()) // As I understand this is safe 
     { 
      // does something 
     } 
    } 

    std::unique_ptr<BigClassCreatedOnce> m_bigClass; 
    std::thread m_thread; 
}; 

サンプルを簡略化するために無限ループに入れています。私はunique_ptr != nullptrをチェックすると

int main() 
{ 
    MainClass ms; 
    while (1) 
    { 
     std::this_thread::sleep_for(std::chrono::milliseconds(1)); 
    } 
} 
+1

なぜ 'm_bigClass'が設定された後にスレッドを作成しないのですか? –

+0

もし私がコメントすれば "m_bigClassへのアクセスはそうではないので、そこにデータ競争があるかもしれません。"私が理解しているように、それは状況を修正しないでしょうか? –

答えて

2

、それは

いいえ、それはスレッドセーフではありませんスレッドセーフです。複数のスレッドがあり、そのうちの少なくとも1つが共有データに書き込む場合、同期が必要です。あなたがデータレースを持っていない場合、それは未定義の動作です。

m_bigClass.reset(new BigClassCreatedOnce()); // created only once 

if (!m_bigClass) 

の両方が同時に起こるので、データ競合であることができます。

私も

if (m_bigClass->var.load()) 

はスレッドセーフではないにもされていることを指摘したいと思います。 var.load()ですが、m_bigClassのアクセスはありませんので、そこにデータ競争もあります。

+0

正しく使用するには?私はunique_ptrにatomicを使用している人を見たことがなく、この状況でどのようにコードがわからないのですか?私は単にmutexを使うべきでしょうか、あるいは別の方法で存在するかもしれませんか? –

+2

@YuriiKomarnytskyiあなたは 'mutex'を使うことができます。あるいは、アトミックフリー関数のオーバーロードを持つ' std :: shared_ptr'に変更することができます。私はそれらがunique_ptrのために存在していない理由は、それが一意であると考えられ、したがって共有されていないためだと考えています。 – NathanOliver

+0

"一意であることが必要なため、shared_ではない"は計算しません。 – curiousguy