在多线程代码中使用shared_ptr

时间:2012-03-24 08:15:39

标签: c++ multithreading boost

在多线程环境中有一个“有效”的示例代码:

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。由于代码具有多个线程,因此在m_pDBif (...)之间由另一个线程重置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. 是否可以保证编译器将pDB声明为boost::shared_ptr<CSampleDatabase>而不是CSampleDatabase *?写decltype(m_pDB) pDb = m_pDB; //lock可能更安全吗?

1 个答案:

答案 0 :(得分:2)

提出的解决方案并不安全。它类似于the documentation中的此示例:

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

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

从同一个实例同时读取是安全的。同一实例上的任何其他并发操作都不是。

  

是否有&#34;标准&#34;如何在不涉及储物柜,互斥锁,关键部分等的情况下防止这种情况?像使用boost :: weak_ptr打破循环引用一样。

您需要互斥,因此您需要使用互斥构造。

  

是否可以保证编译器将pDB声明为boost::shared_ptr<CSampleDatabase>而不是CSampleDatabase *?写decltype(m_pDB) pDb = m_pDB; //lock可能更安全吗?

是的,pDB将是shared_ptr