efficient thread-safe singleton in C++
Your solution is called 'double checked locking' and the way you've written it is not threadsafe.
This Meyers/Alexandrescu paper explains why - but that paper is also widely misunderstood. It started the 'double checked locking is unsafe in C++' meme - but its actual conclusion is that double checked locking in C++ can be implemented safely, it just requires the use of memory barriers in a non-obvious place.
The paper contains pseudocode demonstrating how to use memory barriers to safely implement the DLCP, so it shouldn't be difficult for you to correct your implementation.
Thread-safe singleton in C++11
Static variables are NOT allocated on the stack. In the first variant you have a static pointer (a global variable) initialized with a memory obtained from the heap, while in the second one you have whole static object.
Both versions use internal compiler guards (namely __cxa_guard_acquire()
and __cxa_guard_release()
, which are functionally equivalent to mutex::lock()
and mutex::unlock()
) to ensure serialized access to a special variable that tells whether or not your global instances are already initialized or not.
Your code:
Foo& getInst()
{
static Foo inst(...);
return inst;
}
will actually look like that after the compilation:
Foo& getInst()
{
static Foo inst; // uninitialized - zero
static guard instGuard; // zero
if (is_initialized(instGuard) == false)
{
__cxa_guard_acquire(instGuard);
// do the initialization here - calls Foo constructor
set_initialized(instGuard);
__cxa_guard_release(instGuard);
}
return inst;
}
So both of your exampes are thread safe.
How to implement multithread safe singleton in C++11 without using mutex
C++11 removes the need for manual locking. Concurrent execution shall wait if a static local variable is already being initialized.
§6.7 [stmt.dcl] p4
If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.
As such, simple have a static
function like this:
static Singleton& get() {
static Singleton instance;
return instance;
}
This will work all-right in C++11 (as long as the compiler properly implements that part of the standard, of course).
Of course, the real correct answer is to not use a singleton, period.
Thread Safe singleton in C++ using static member instance (no lazy instantiation)
If you change the singleton instance to be a static class member, the creation of that instance will be thread safe. Whatever you do with it, will of cause still need to be protected in many cases.
Also see When are static C++ class members initialized?
Is this Singleton Implementation Thread-Safe?
It is hard to beat a simple
class Singleton { ... };
Singleton* get_instance()
{
static Singleton instance; // guaranteed to be thread safe in C++11
return &instance;
}
Any access to the pointer after it has been returned is still not thread safe, but neither is access in your implementation.
Make Meyers' Singleton thread safe and fast with lazy evaluation
So seems the answer to my question best expressed Fred Larson in his comment:
"Fast, thread-safe, lazy - pick any two."
Thread safe singleton in C++
Not a good idea. Look for double check locking. For instance:
http://www.drdobbs.com/cpp/c-and-the-perils-of-double-checked-locki/184405726
http://www.drdobbs.com/cpp/c-and-the-perils-of-double-checked-locki/184405772
Related Topics
Opengl Define Vertex Position in Pixels
How to Set File Permissions (Cross Platform) in C++
Function Overloading Based on Value VS. Const Reference
Converting String of 1S and 0S into Binary Value
Why Can't I Write to a String Literal While I *Can* Write to a String Object
What Does "#Pragma Comment" Mean
Why Can't I Capture This By-Reference ('&This') in Lambda
C++ Preprocessor: Avoid Code Repetition of Member Variable List
Explain C++ Sfinae to a Non-C++ Programmer
Fast N Choose K Mod P for Large N
Portability of Binary Serialization of Double/Float Type in C++
Why Are Strings in C++ Usually Terminated with '\0'
Tell Cin to Stop Reading at Newline
What Is the Status of N2965 - Std::Bases and Std::Direct_Bases
Why Is Initializing an Integer in C++ to 010 Different from Initializing It to 10
Is There a Production Ready Lock-Free Queue or Hash Implementation in C++