2017-06-14 57 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