In the following singleton 'get' function, can other threads see instance as not-null, but almost_done still false? (Say almost_done is initially 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;
}
If they can, why? What's the rationale?
I know nothing can "get out" of an acquire-release section, but can't 2 enter it and be reordered with 1?
I'm aware I don't need such complex techniques for thread-safe singletons in C++, and yes, there's not much sense in almost_done, this is purely for learning.
Your code shows a valid implementation of the Double-Checked-Locking pattern (DCLP).
Synchronization is handled by either the std::mutex or std::atomic::instance depending on the order in which threads enter the code.
can other threads see instance as not-null, but almost_done still false?
No, this is not possible.
The DCLP pattern guarantees that all threads that perform a load-acquire (that returns a non-null value) at the beginning, are guaranteed to see instance point at valid memory and almost_done==true
because the load has synchronized with the store-release.
A reason one might think it is possible, is in the small window of opportunity where the first thread (#1) is holding the std::mutex while a second thread (#2) is entering the first if-statement.
Before #2 locks the std::mutex, it may observe a value for instance (still pointing at unsynchronized memory because the mutex is responsible for that, but hasn't synchronized yet).
But even if that happens (a valid scenario in this pattern), #2 will see almost_done==true since the release fence (called by #1) orders the store-relaxed to almost_done
before the store-relaxed to instance and that same order is observed by other threads.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With