在这样的单例实现中可以对两个商店进行重新排序吗?
Can two stores be reordered in such singleton implementation?
在下面的单例'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;
}
如果可以,为什么?理由是什么?
我不知道什么可以 "get out" 获取发布部分,但不能 2
输入它并用 1
重新排序?
我知道在 C++ 中我不需要如此复杂的线程安全单例技术,是的,在 almost_done
中没有太大意义,这纯粹是为了学习。
您的代码显示了双重检查锁定模式 (DCLP) 的有效实现。
同步由 std::mutex
或 std::atomic::instance
处理,具体取决于线程输入代码的顺序。
can other threads see instance as not-null, but almost_done still false?
不,这是不可能的。
DCLP 模式保证所有线程在开始时执行加载获取(returns 非空值),保证看到 instance
指向有效内存和 almost_done==true
因为加载已经和store-release同步了。
人们可能认为这是可能的一个原因是,第一个线程 (#1) 持有 std::mutex
而第二个线程 (#2) 持有 window 的机会很小输入第一个 if
语句。
在#2 锁定 std::mutex
之前,它可能会观察到 instance
的值(仍然指向未同步的内存,因为互斥体对此负责,但尚未同步)。
但即使发生这种情况(此模式中的有效场景),#2 也会看到 almost_done==true
,因为释放栅栏(由 #1 调用)命令存储松弛到 almost_done
在 store-relaxed 到 instance
之前,其他线程观察到相同的顺序。
在下面的单例'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;
}
如果可以,为什么?理由是什么?
我不知道什么可以 "get out" 获取发布部分,但不能 2
输入它并用 1
重新排序?
我知道在 C++ 中我不需要如此复杂的线程安全单例技术,是的,在 almost_done
中没有太大意义,这纯粹是为了学习。
您的代码显示了双重检查锁定模式 (DCLP) 的有效实现。
同步由 std::mutex
或 std::atomic::instance
处理,具体取决于线程输入代码的顺序。
can other threads see instance as not-null, but almost_done still false?
不,这是不可能的。
DCLP 模式保证所有线程在开始时执行加载获取(returns 非空值),保证看到 instance
指向有效内存和 almost_done==true
因为加载已经和store-release同步了。
人们可能认为这是可能的一个原因是,第一个线程 (#1) 持有 std::mutex
而第二个线程 (#2) 持有 window 的机会很小输入第一个 if
语句。
在#2 锁定 std::mutex
之前,它可能会观察到 instance
的值(仍然指向未同步的内存,因为互斥体对此负责,但尚未同步)。
但即使发生这种情况(此模式中的有效场景),#2 也会看到 almost_done==true
,因为释放栅栏(由 #1 调用)命令存储松弛到 almost_done
在 store-relaxed 到 instance
之前,其他线程观察到相同的顺序。