【发布时间】:2020-07-19 21:07:35
【问题描述】:
private std::unique_ptr<MyClass> myptr_;
LazyInit()
{
// Assume mutex lock. Skipping specifics since it is not relevant for this question
auto mylock = LOCK();
if(!myptr_)
{
// myptr_ is only initialized once ever. Once assigned it is never deleted till end of process.
myptr_ = make_unique<MyClass>();
}
// lock released when mylock goes out of scope.
}
Read()
{
// No locking here.
// Expectation: myptr_ is either null or valid value. Totally fine if myptr_ just got assigned, next call to Read will read the value.
if(myptr_)
{
myptr_->DoSomething();
}
}
问题:是否保证当 Read() 执行时,myptr_ 要么为空,要么有一个有效值? (具体来说,在 LazyInit 中对 myptr_ 的赋值是否是原子的,关于内存对齐?) 假设 LazyInit 和 Read 都可以被多个线程调用。
根据下面的文档,似乎 myptr_ 可能有一个垃圾值(除了 null 或有效值)。有人可以通过确认/否认我的理解来澄清这一点吗?
相关文档:(https://docs.microsoft.com/en-us/cpp/standard-library/thread-safety-in-the-cpp-standard-library?view=vs-2019) “如果一个对象正在被一个线程写入,那么在同一个或其他线程上对该对象的所有读写都必须受到保护。例如,给定一个对象 A,如果线程 1 正在写入 A,那么线程 2 必须被阻止读取或写入 A。"
【问题讨论】:
-
您已经引用了相关部分:如果一个对象正在由一个线程写入,那么 所有读取和写入到同一线程或其他线程上的该对象必须受到保护。您在
Read中的读取操作不受保护;因此,你有一个数据竞赛。
标签: c++ concurrency stl thread-safety unique-ptr