假设我们有一个类型为Wrapper
的全局对象,该对象具有不是nullptr的std::unique_ptr<MyObject> m_pUnique
成员。然后在线程1中将m_pUnique
设置为nullptr,因此将调用MyObject
的析构函数,然后该线程退出。线程1退出后,线程2调用Wrapper对象的析构函数。问题是:
m_pUnique
为nullptr?(我听说线程退出时会发生一些内存排序(这种情况是线程1),但不确定读取m_pUnique指针值(而不读取其内部对象值)的线程2是否会看到新的指针值。) >m_pUnique
现在为nullptr,是否有可能再次调用m_pUnique
的MyObject
的析构函数?简化代码示例:
class Wrapper
{
public:
std::unique_ptr<MyObject> m_pUnique;
}
//Global var created somewhere e.g. in thread 0
Wrapper* someWrapper = new Wrapper();
someWrapper.reset(new MyObject);
//...
//sets m_pUnique to nullptr, which calls MyObject's destructor and then threads exits
Thread1Func()
{
someWrapper.m_pUnique = nullptr;
}
//delete Wrapper object after thread 1 has exited
Thread2Func()
{
delete someWrapper;
}
假设我们有一个Wrapper类型的全局对象,它的std :: unique_ptr
如果线程2已经从someWrapper读取m_pUnique,那么除非保证该成员被标记为volatile或原子化,否则不能保证(不暗示障碍)它将发现m_pUnique已更改。
但是,在调用析构函数时,将运行必须重新检查对象的不同代码,因此,假设您的CPU支持缓存和核心一致性,则析构函数将看到m_pUnique已经为nullptr。这样可以防止目标对象被双重破坏。