I have read many questions considering thread-safe double checked locking (for singletons or lazy init). In some threads, the answer is that the pattern is entirely broken, others suggest a solution.
So my question is: Is there a way to write a fully thread-safe double checked locking pattern in C++? If so, how does it look like.
We can assume C++11, if that makes things easier. As far as I know, C++11 improved the memory model which could yield the needed improvements.
I do know that it is possible in Java by making the double-check guarded variable volatile. Since C++11 borrowed large parts of the memory model from the one of Java, so I think it could be possible, but how?
Simply use a static local variable for lazily initialized Singletons, like so:
MySingleton* GetInstance() {
static MySingleton instance;
return &instance;
}
The (C++11) standard already guarantees that static variables are initialized in a threadsafe manner and it seems likely that the implementation of this at least as robust and performant as anything you'd write yourself.
The threadsafety of the initialization can be found in §6.7.4 of the (C++11) standard:
If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.
Since you wanted to see a valid DCLP C++11 implementation, here is one.
The behavior is fully thread-safe and identical to GetInstance() in Grizzly's answer.
std::mutex mtx;
std::atomic<MySingleton *> instance_p{nullptr};
MySingleton* GetInstance()
{
auto *p = instance_p.load(std::memory_order_acquire);
if (!p)
{
std::lock_guard<std::mutex> lck{mtx};
p = instance_p.load(std::memory_order_relaxed);
if (!p)
{
p = new MySingleton;
instance_p.store(p, std::memory_order_release);
}
}
return p;
}
Related
I recently came across some code that was working fine where a static bool was shared between multiple threads (single writer, multiple receivers) although there was no synchronization.
Something like that (simplified):
//header A
struct A {
static bool f;
static bool isF() { return f; }
};
//Source A
bool A::f = false;
void threadWriter(){
/* Do something */
A::f = true;
}
// Source B
void threadReader(){
while (!A::isF()) { /* Do something */}
}
For me, this kind of code has a race condition in that even though operations on bool are atomic (on most CPUs), we have no guarantee that the write from the writer thread will be visible to the reader threads. But some people told me that the fact that f is static would help.
So, is there anything in C++11 that would make this code safe? Or anything related to static that would make this code work?
Your hardware may be able to atomically operate on a bool. However, that does not make this code safe. As far as C++ is concerned, you are writing and reading the bool in different threads without synchronisation, which is undefined.
Making the bool static does not change that.
To access the bool in a thread-safe way you can use a std::atomic<bool>. Whether the atomic uses a mutex or other locking is up to the implementation.
Though, also a std::atomic<bool> is not sufficient to synchronize the threadReader() and threadWriter() in case each /*Do something */ is accessing the same shared data.
But some people told me that the fact that f is static would help.
Frankly, this sounds like cargo-cult. I can imagine that this was confused with the fact that initialization of static local variables is thread safe. From cppreference:
If multiple threads attempt to initialize the same static local
variable concurrently, the initialization occurs exactly once (similar
behavior can be obtained for arbitrary functions with std::call_once).
Note: usual implementations of this feature use variants of the
double-checked locking pattern, which reduces runtime overhead for
already-initialized local statics to a single non-atomic boolean
comparison.
Look for Meyers singleton to see an example of that. Though, this is merely about initialization. For example here:
int& foo() {
static int x = 42;
return x;
}
Two threads can call this function concurrently and x will be initialized exactly once. This has no impact on thread-safety of x itself. If two threads call foo and one writes and another reads x there is a data race. However, this is about initialization of static local variables and has nothing to do with your example. I don't know what they meant when they told you static would "help".
I'm a bit confused about the purpose of std::call_once. To be clear, I understand exactly what std::call_once does, and how to use it. It's usually used to atomically initialize some state, and make sure that only one thread initializes the state. I've also seen online many attempts to create a thread-safe singleton with std::call_once.
As demonstrated here, suppose you write a thread safe singleton, as such:
CSingleton& CSingleton::GetInstance()
{
std::call_once(m_onceFlag, [] {
m_instance.reset(new CSingleton);
});
return *m_instance.get();
}
Okay, I get the idea. But I thought that the only thing std::call_once really guarantees is that the passed function will only be executed once. But does it also guarantee that if there is a race to call the function between multiple threads, and one thread wins, the other threads will block until the winning thread returns from the call?
Because if so, I see no difference between call_once and a plain synchronization mutex, like:
CSingleton& CSingleton::GetInstance()
{
std::unique_lock<std::mutex> lock(m_mutex);
if (!m_instance)
{
m_instance.reset(new CSingleton);
}
lock.unlock();
return *m_instance;
}
So, if std::call_once indeed forces other threads to block, then what benefits does std::call_once offer over a regular mutex? Thinking about it some more, std::call_once would certainly have to force the other threads to block, or whatever computation was accomplished in the user-provided function wouldn't be synchronized. So again, what does std::call_once offer above an ordinary mutex?
One thing that call_once does for you is handle exceptions. That is, if the first thread into it throws an exception inside of the functor (and propagates it out), call_once will not consider the call_once satisfied. A subsequent invocation is allowed to enter the functor again in an effort to complete it without an exception.
In your example, the exceptional case is also handled properly. However it is easy to imagine a more complicated functor where the exceptional case would not be properly handled.
All this being said, I note that call_once is redundant with function-local-statics. E.g.:
CSingleton& CSingleton::GetInstance()
{
static std::unique_ptr<CSingleton> m_instance(new CSingleton);
return *m_instance;
}
Or more simply:
CSingleton& CSingleton::GetInstance()
{
static CSingleton m_instance;
return m_instance;
}
The above is equivalent to your example with call_once, and imho, simpler. Oh, except the order of destruction is very subtly different between this and your example. In both cases m_instance is destroyed in reverse order of construction. But the order of construction is different. In your m_instance is constructed relative to other objects with file-local scope in the same translation unit. Using function-local-statics, m_instance is constructed the first time GetInstance is executed.
That difference may or may not be important to your application. Generally I prefer the function-local-static solution as it is "lazy". I.e. if the application never calls GetInstance() then m_instance is never constructed. And there is no period during application launch when a lot of statics are trying to be constructed at once. You pay for the construction only when actually used.
Slight variation on standard C++ solution is to use lambda inside the usual one:
// header.h
namespace dbj_once {
struct singleton final {};
inline singleton & instance()
{
static singleton single_instance = []() -> singleton {
// this is called only once
// do some more complex initialization
// here
return {};
}();
return single_instance;
};
} // dbj_once
Please observe
anonymous namespace implies default static linkage for variables inside. Thus do not put this inside it. This is header code.
worth repeating: this is safe in presence of multiple threads (MT) and is supported as a such by all major compilers
inside is a lambda which is guaranteed to be called only once
this pattern is also safe to use in header only situations
If you read this you'll see that std::call_once makes no guarantee about data-races, it's simply a utility function for performing an action once (which will work across threads). You shouldn't presume that is has anything close to the affect of a mutex.
as an example:
#include <thread>
#include <mutex>
static std::once_flag flag;
void f(){
operation_that_takes_time();
std::call_once(flag, [](){std::cout << "f() was called\n";});
}
void g(){
operation_that_takes_time();
std::call_once(flag, [](){std::cout << "g() was called\n";});
}
int main(int argc, char *argv[]){
std::thread t1(f);
std::thread t2(g);
t1.join();
t2.join();
}
could print both f() was called and g() was called. This is because in the body of std::call_once it will check whether flag was set then set it if not then call the appropriate function. But while it is checking or before it set flag another thread may call call_once with the same flag and run a function at the same time. You should still protect calls to call_once with a mutex if you know another thread may have a data race.
EDIT
I found a link to the proposal for the std::call_once function and thread library which states that concurrency is guaranteed to only call the function once, so it should work like a mutex (y)
More specifically:
If multiple calls to call_once with the same flag are executing concurrently in separate threads, then only one thread shall call func, and no thread shall proceed until the call to func has completed.
So to answer your question: yes, other threads will be blocked until the calling thread returns from the specified functor.
This question already has answers here:
Double-Checked Lock Singleton in C++11
(3 answers)
Closed 9 years ago.
Here is a Java example problem from http://www.ibm.com/developerworks/java/library/j-dcl/index.html
public static Singleton getInstance()
{
if (instance == null) //#4
{
synchronized(Singleton.class) { //#1
if (instance == null) //#2
instance = new Singleton(); //#3
}
}
return instance;
}
It seems this isn't safe because #3 can set instance to not null before the constructor is executed thus when another thread checks instance on #4 it will not be null and return a instance that hasn't been constructed properly.
Apparently using a function variable wont help because it may be optimized out or just be executed in a way that also sets the value to instance when we don't want it to.
I was thinking wouldn't the easiest way is to have a function new Singleton(); so it is completed before assigning it to instance. Now the issue is how do I tell C++ a function should NOT be inline? I think Singleton* make_singleton() volatile should do that but i'm positive I am wrong.
I'll ignore the singleton bits for a while and assume you need this for lazy initialization and not for silly things like singletons.
I suggest forgetting about double-checked locking. C++ provides a very useful tool for this kind of situation in the form of std::call_once, so use that.
template <typename T>
struct lazy {
public:
// needs constraining to prevent from doing copies
// see: http://flamingdangerzone.com/cxx11/2012/06/05/is_related.html
template <typename Fun>
explicit lazy(Fun&& fun) : fun(std::forward<Fun>(fun)) {}
T& get() const {
std::call_once(flag, [this] { ptr.reset(fun()); });
return *ptr;
}
// more stuff like op* and op->, implemented in terms of get()
private:
std::once_flag flag;
std::unique_ptr<T> ptr;
std::function<T*()> fun;
};
// --- usage ---
lazy<foo> x([] { return new foo; });
This is exactly the type of situation atomics are designed for. By storing the result into an atomic, you know that the compiler can't sequence any critical stores or operations after the atomic is set. Atomics are both for emitting processor instruction primitives to ensure the necessary sequential consistency (e.g., for cache coherency across cores) and for telling the compiler which semantics must be preserved (and therefore to limit the types of reorderings it can do). If you use an atomic here, it won't matter if the function is inlined because whatever inlining the compiler does will have to preserve the semantics of the atomic itself.
You may also be interested in looking into std::call_once which is also designed for this situation, and more specifically for the situation where multiple threads may need something done, but exactly one of them should do it.
Is the following singleton implementation data-race free?
static std::atomic<Tp *> m_instance;
...
static Tp &
instance()
{
if (!m_instance.load(std::memory_order_relaxed))
{
std::lock_guard<std::mutex> lock(m_mutex);
if (!m_instance.load(std::memory_order_acquire))
{
Tp * i = new Tp;
m_instance.store(i, std::memory_order_release);
}
}
return * m_instance.load(std::memory_order_relaxed);
}
Is the std::memory_model_acquire of the load operation superfluous? Is it possible to further relax both load and store operations by switching them to std::memory_order_relaxed? In that case, is the acquire/release semantic of std::mutex enough to guarantee its correctness, or a further std::atomic_thread_fence(std::memory_order_release) is also required to ensure that the writes to memory of the constructor happen before the relaxed store? Yet, is the use of fence equivalent to have the store with memory_order_release?
EDIT: Thanks to the answer of John, I came up with the following implementation that should be data-race free. Even though the inner load could be non-atomic at all, I decided to leave a relaxed load in that it does not affect the performance. In comparison to always have an outer load with the acquire memory order, the thread_local machinery improves the performance of accessing the instance of about an order of magnitude.
static Tp &
instance()
{
static thread_local Tp *instance;
if (!instance &&
!(instance = m_instance.load(std::memory_order_acquire)))
{
std::lock_guard<std::mutex> lock(m_mutex);
if (!(instance = m_instance.load(std::memory_order_relaxed)))
{
instance = new Tp;
m_instance.store(instance, std::memory_order_release);
}
}
return *instance;
}
I think this a great question and John Calsbeek has the correct answer.
However, just to be clear a lazy singleton is best implemented using the classic Meyers singleton. It has garanteed correct semantics in C++11.
§ 6.7.4
... If control enters
the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for
completion of the initialization. ...
The Meyer's singleton is preferred in that the compiler can aggressively optimize the concurrent code. The compiler would be more restricted if it had to preserve the semantics of a std::mutex. Furthermore, the Meyer's singleton is 2 lines and virtually impossible to get wrong.
Here is a classic example of a Meyer's singleton. Simple, elegant, and broken in c++03. But simple, elegant, and powerful in c++11.
class Foo
{
public:
static Foo& instance( void )
{
static Foo s_instance;
return s_instance;
}
};
That implementation is not race-free. The atomic store of the singleton, while it uses release semantics, will only synchronize with the matching acquire operation—that is, the load operation that is already guarded by the mutex.
It's possible that the outer relaxed load would read a non-null pointer before the locking thread finished initializing the singleton.
The acquire that is guarded by the lock, on the other hand, is redundant. It will synchronize with any store with release semantics on another thread, but at that point (thanks to the mutex) the only thread that can possibly store is the current thread. That load doesn't even need to be atomic—no stores can happen from another thread.
See Anthony Williams' series on C++0x multithreading.
See also call_once.
Where you'd previously use a singleton to do something, but not actually use the returned object for anything, call_once may be the better solution.
For a regular singleton you could do call_once to set a (global?) variable and then return that variable...
Simplified for brevity:
template< class Function, class... Args>
void call_once( std::once_flag& flag, Function&& f, Args&& args...);
Exactly one execution of exactly one of the functions, passed as f to the invocations in the group (same flag object), is performed.
No invocation in the group returns before the abovementioned execution of the selected function is completed successfully
As Scott Meyers and Andrei Alexandrescu outlined in this article the simple try to implement the double-check locking implementation is unsafe in C++ specifically and in general on multi-processor systems without using memory barriers.
I was thinking a little bit about that and came to a solution that avoids using memory barriers and should also work 100% safe in C++. The trick is to store a copy of the pointer to the instance thread-local so each thread has to acquire the lock for the first times it access the singleton.
Here is a little sample code (syntax not checked; I used pthread but all other threading libs could be used):
class Foo
{
private:
Helper *helper;
pthread_key_t localHelper;
pthread_mutex_t mutex;
public:
Foo()
: helper(NULL)
{
pthread_key_create(&localHelper, NULL);
pthread_mutex_init(&mutex);
}
~Foo()
{
pthread_key_delete(&localHelper);
pthread_mutex_destroy(&mutex);
}
Helper *getHelper()
{
Helper *res = pthread_getspecific(localHelper);
if (res == NULL)
{
pthread_mutex_lock(&mutex);
if (helper == NULL)
{
helper = new Helper();
}
res = helper;
pthread_mutex_unlock(&mutex);
pthread_setspecific(localHelper, res);
}
return res;
}
};
What are your comments/opinions?
Do you find any flaws in the idea or the implementation?
EDIT:
Helper is the type of the singleton object (I know the name is not the bet...I took it from the Java examples in the Wikipedia article about DCLP).
Foo is the Singleton container.
EDIT 2:
Because it seems to be a little bit misunderstanding that Foo is not a static class and how it is used, here an example of the usage:
static Foo foo;
.
.
.
foo.getHelper()->doSomething();
.
.
.
The reason that Foo's members are not static is simply that I was able to create/destroy the mutex and the TLS in the constructor/destructor.
If a RAII version of a C++ mutex / TLS class is used Foo can easily be switched to be static.
You seem to be calling:
pthread_mutex_init(&mutex);
...in the Helper() constructor. But that constructor is itself called in the function getHelper() (which should be static, I think) which uses the mutex. So the mutex appears to be initialised twice or not at all.
I find the code very confusing, I must say. Double-checked locking is not that complex. Why don't you start again, and this time create a Mutex class, which does the initialisation, and uses RAI to release the underlying pthread mutex? Then use this Mutex class to implement your locking.
This isn't the double-checked locking pattern. Most of the potential thread safety issues of the pattern are due to the fact the the a common state is read outside of a mutually exclusive lock, and then re-checked inside it.
What you are doing is checking a thread local data item, and then checking the common state inside a lock. This is more like a standard single check singleton pattern with a thread local cached value optimization.
To a casual glance it does look safe, though.
Looks interesting! Clever use of thread-local storage to reduce contention.
But I wonder if this is really different from the problematic approach outlined by Meyers/Alexandrescu...?
Say you have two threads for which the singleton is uninitialized (e.g. thread local slot is empty) and they run getHelper in parallel.
Won't they get into the same race over the helper member? You're still calling operator new and you're still assigning that to a member, so the risk of rogue reordering is still there, right?
EDIT: Ah, I see now. The lock is taken around the NULL-check, so it should be safe. The thread-local replaces the "first" NULL-check of the DCLP.
Obviously a few people are misunderstanding your intent/solution. Something to think about.
I think the real question to be asked is this:
Is calling pthread_getspecific() cheaper than a memory barrier?
Are you trying to make a thread-safe singleton or, implement Meyers & Andrescu's tips? The most straightforward thing is to use a
pthread_once
as is done below. Obviously you're not going for lock-free speed or anything, creating & destroying mutexes as you are so, the code may as well be simple and clear - this is the kind of thing pthread_once was made for. Note, the Helper ptr is static, otherwise it'd be harder to guarantee that there's only one Helper object:
// Foo.h
#include <pthread.h>
class Helper {};
class Foo
{
private:
static Helper* s_pTheHelper;
static ::pthread_once_t once_control;
private:
static void createHelper() { s_pTheHelper = new Helper(); }
public:
Foo()
{ // stuff
}
~Foo()
{ // stuff
}
static Helper* getInstance()
{
::pthread_once(&once_control, Foo::createHelper);
return s_pTheHelper;
}
};
// Foo.cpp
// ..
Helper* Foo::s_pTheHelper = NULL;
::pthread_once_t Foo::once_control = PTHREAD_ONCE_INIT;
// ..