Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement multithread safe singleton in C++11 without using <mutex>

Now that C++11 has multithreading I was wondering what is the correct way to implement lazy initialized singleton without using mutexes(for perf reasons). I came up with this, but tbh Im not really good at writing lockfree code, so Im looking for some better solutions.

// ConsoleApplication1.cpp : Defines the entry point for the console application. // # include <atomic> # include <thread> # include <string> # include <iostream> using namespace std; class Singleton {  public:     Singleton()     {     } static  bool isInitialized()     {         return (flag==2);     } static  bool initizalize(const string& name_)     {         if (flag==2)             return false;// already initialized         if (flag==1)             return false;//somebody else is initializing         if (flag==0)         {             int exp=0;             int desr=1;             //bool atomic_compare_exchange_strong(std::atomic<T>* obj, T* exp, T desr)             bool willInitialize=std::atomic_compare_exchange_strong(&flag, &exp, desr);             if (! willInitialize)             {                 //some other thread CASed before us                 std::cout<<"somebody else CASed at aprox same time"<< endl;                 return false;             }             else              {                 initialize_impl(name_);                 assert(flag==1);                 flag=2;                 return true;             }         }     } static void clear() {     name.clear();     flag=0; } private: static  void initialize_impl(const string& name_) {         name=name_; } static  atomic<int> flag; static  string name; }; atomic<int> Singleton::flag=0; string Singleton::name; void myThreadFunction() {     Singleton s;     bool initializedByMe =s.initizalize("1701");     if (initializedByMe)         s.clear();  } int main() {     while (true)     {         std::thread t1(myThreadFunction);         std::thread t2(myThreadFunction);         t1.join();         t2.join();     }     return 0; } 

Note that clear() is just for testing, real singleton wouldnt have that function.

like image 446
NoSenseEtAl Avatar asked Jul 29 '12 18:07

NoSenseEtAl


People also ask

How do you handle singleton in multithreading?

Thread Safe Singleton in JavaCreate the private constructor to avoid any new object creation with new operator. Declare a private static instance of the same class. Provide a public static method that will return the singleton class instance variable.

How a singleton implementation can be thread safe?

Thread Safe Singleton: A thread safe singleton is created so that singleton property is maintained even in multithreaded environment. To make a singleton class thread safe, getInstance() method is made synchronized so that multiple threads can't access it simultaneously.

Is Meyers singleton thread safe?

The beauty of the Meyers Singleton in C++11 is that it's automatically thread-safe. That is guaranteed by the standard: Static variables with block scope. The Meyers Singleton is a static variable with block scope, so we are done.

Are singletons thread safe C#?

How to Implement Singleton Pattern in C# code. There are several ways to implement a Singleton Pattern in C#. No Thread Safe Singleton.


2 Answers

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.

like image 90
Xeo Avatar answered Oct 25 '22 22:10

Xeo


Maybe the easiest way to implement a singleton using C++11 is:

WARNING: Although this works according to the C++11 standard (static initialisers are thread-safe), this is not implemented correctly in Microsoft Visual C++ 2012 (static initialisers are NOT thread-safe). If you are targeting VC2012, then you have to use a different approach, as it does not fully implement the C++11 standard.

class Singleton {  public:   static Singleton& Instance() {     // Since it's a static variable, if the class has already been created,     // it won't be created again.     // And it **is** thread-safe in C++11.     static Singleton myInstance;      // Return a reference to our instance.     return myInstance;   }    // delete copy and move constructors and assign operators   Singleton(Singleton const&) = delete;             // Copy construct   Singleton(Singleton&&) = delete;                  // Move construct   Singleton& operator=(Singleton const&) = delete;  // Copy assign   Singleton& operator=(Singleton &&) = delete;      // Move assign    // Any other public methods.   protected:   Singleton() {     // Constructor code goes here.   }    ~Singleton() {     // Destructor code goes here.   }   // And any other protected methods. } 
like image 23
GutiMac Avatar answered Oct 25 '22 23:10

GutiMac