2017-06-14 60 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; 
}; 

我只是把它放到无限循环来简化样本。

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

为什么不在'm_bigClass'设置后创建线程? –

+0

如果我这样做,评论“m_bigClass的访问不是这样,你也可以在那里有一个数据竞赛。”据我了解,这也不能解决这种情况? –

回答

2

如果我检查unique_ptr != nullptr,是线程安全

不,这不是线程安全的。如果您有多个线程,并且其中至少有一个线程写入共享数据,则需要同步。如果你没有,那么你有一个数据竞争,这是未定义的行为。

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

if (!m_bigClass) 

既可以发生在同一时间,所以它是一个数据的比赛。

我也想指出的是,

if (m_bigClass->var.load()) 

也不是线程安全的。 var.load()是,但m_bigClass的访问不是这样,你也可以在那里有一个数据竞赛。

+0

它应该如何正确使用?我从来没有见过有人使用atomic来unique_ptr,但不知道在这种情况下代码如何。我应该简单地使用互斥锁还是以其他方式存在? –

+2

@YuriiKomarnytskyi你可以使用'mutex',或者你可以改变为'std :: shared_ptr',它确实有原子自由函数的重载。我相信他们对'unique_ptr'不存在的推理是因为它应该是唯一的,因此不能共享。 – NathanOliver

+0

“_supposed是唯一的,因此不shared_”不计算;) – curiousguy