【问题标题】:Are std::unique_ptr assignments and reading thread safe with respect to control block?std::unique_ptr 分配和读取线程对于控制块是否安全?
【发布时间】: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


【解决方案1】:

不,不能保证。 std::unique_ptr 的赋值运算符未记录为线程安全的。 bool 运算符重载也没有记录为线程安全的。

对于 C++ 库,除非明确指定为线程安全,否则不是。除非您可以在 C++ 类或其方法中找到它明确线程安全的文档,否则它不是。

【讨论】:

    猜你喜欢
    • 2013-05-05
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    • 2021-12-19
    • 2011-11-04
    • 1970-01-01
    • 2011-01-14
    • 1970-01-01
    相关资源
    最近更新 更多