2012-03-24 33 views
1

有一個示例代碼在多線程環境中「工作」:在多線程代碼中使用shared_ptr

void CSampleClass::Stop(void) { 
    if (m_pDB != nullptr) { 
    ... Here is some code 
    m_pDB->Interrupt(); 
    } 
}
,其中 m_pDB成員聲明爲 boost::shared_ptr<CSampleDatabase> m_pDB;m_pDB可以在另一個類的方法中重置。這就是爲什麼它被測試不是 nullptr。由於代碼具有多個線程,因此被另一個線程重置,在 if (...)m_pDB->Interrupt();之間時,可以是 情況。結果是相當戲劇性的。爲了防止出現這種情況,我使用以下代碼修改
void CSampleClass::Stop(void) { 
    auto pDb = m_pDB; //lock 
    if (pDb != nullptr) { 
    ... Here is some code 
    pDb->Interrupt(); 
    } 
}
,即如果調用了 m_pDB.reset();,則在銷燬 pDb之前,對象永遠不會被釋放。

的問題是:

  1. 是否有一個「標準」的方式,以防止情況不涉及儲物櫃,互斥,臨界區等?像使用boost::weak_ptr來打破循環引用。

  2. 確保編譯器聲明pDBboost::shared_ptr<CSampleDatabase>而不是CSampleDatabase *?可能是寫decltype(m_pDB) pDb = m_pDB; //lock更安全嗎?

+2

第二個版本仍然包含競爭條件。複製構建'shared_ptr'不是一個原子操作。 – Mankarse 2012-03-24 08:28:22

+0

@Mancarse:引用? – 2012-03-24 08:49:54

+0

@nm:從[here](http://www.boost.org/doc/libs/release/libs/smart_ptr/shared_ptr.htm#ThreadSafety):「shared_ptr對象提供與內置相同級別的線程安全性類型」。這意味着多個'shared_ptr'實例引用同一對象並同時修改這些'shared_ptr'是安全的,但同時修改/讀取一個'shared_ptr'實例並不安全。 – Mankarse 2012-03-24 09:05:59

回答

2

提供的解決方案並不安全。它類似於這個例子從the documentation

// thread A 
p = p3; // reads p3, writes p 

// thread B 
p3.reset(); // writes p3; undefined, simultaneous read/write 

同時來自同一個實例讀取是安全的。在同一個實例上的任何其他併發操作都不是。

有沒有一種「標準」方式來防止不涉及儲物櫃,互斥體,臨界區等情況?就像使用boost :: weak_ptr來打破循環引用一樣。

您需要互斥,所以您需要使用互斥構造。

能夠保證所有的編譯器聲明pDBboost::shared_ptr<CSampleDatabase>,而不是CSampleDatabase *?可能是寫decltype(m_pDB) pDb = m_pDB; //lock更安全嗎?

是的,pDB將是shared_ptr

相關問題