在多线程环境中有一个“有效”的示例代码:
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_pDB
和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
被销毁之前,对象永远不会被释放。
问题是:
是否存在“标准”方法来阻止情况而不涉及储物柜,互斥锁,关键部分等?比如使用boost::weak_ptr
打破循环引用。
是否可以保证编译器将pDB
声明为boost::shared_ptr<CSampleDatabase>
而不是CSampleDatabase *
?写decltype(m_pDB) pDb = m_pDB; //lock
可能更安全吗?
答案 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
。