gpt4 book ai didi

c++ - 在这样的单例实现中可以对两个商店进行重新排序吗?

转载 作者:太空狗 更新时间:2023-10-29 21:33:25 26 4
gpt4 key购买 nike

在下面的单例'get'函数中,其他线程是否可以看到instance为not-null,但是almost_done仍然是false? (假设 almost_done 最初是 false。)

Singleton *Singleton::Get() {
auto tmp = instance.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);
if (tmp == nullptr) {
std::lock_guard<std::mutex> guard(lock);
tmp = instance.load(std::memory_order_relaxed);
if (tmp == nullptr) {
tmp = new Singleton();
almost_done.store(true, std::memory_order_relaxed); // 1
std::atomic_thread_fence(std::memory_order_release);
instance.store(tmp, std::memory_order_relaxed); // 2
}
}
return tmp;
}

如果可以,为什么?原理是什么?

我知道什么都不能从获取-发布部分“出去”,但是 2 不能进入它并用 1 重新排序吗?

我知道在 C++ 中我不需要如此复杂的线程安全单例技术,是的,almost_done 没有多大意义,这纯粹是为了学习。

最佳答案

您的代码显示了双重检查锁定模式 (DCLP) 的有效实现。
同步由 std::mutexstd::atomic::instance 处理,具体取决于线程输入代码的顺序。

can other threads see instance as not-null, but almost_done still false?

不,这是不可能的。

DCLP 模式保证所有在开始时执行加载获取(返回非空值)的线程都保证看到 instance 指向有效内存并且 almost_done ==真因为加载已与商店发布同步。

一个人可能认为这是可能的原因是在第一个线程 (#1) 持有 std::mutex 而第二个线程 (#2) 持有的小机会窗口中输入第一个 if 语句。

在 #2 锁定 std::mutex 之前,它可能会观察到 instance 的值(仍然指向未同步的内存,因为互斥锁对此负责,但没有尚未同步)。
但即使发生这种情况(此模式中的有效场景),#2 也会看到 almost_done==true,因为释放栅栏(由 #1 调用)命令 store-relaxed 到 almost_done在 store-relaxed 到 instance 之前,其他线程会观察到相同的顺序。

关于c++ - 在这样的单例实现中可以对两个商店进行重新排序吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51126747/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com