Singleton with multithreads Singleton with multithreads multithreading multithreading

Singleton with multithreads


In C++11, the following is guaranteed to perform thread-safe initialisation:

static Singleton* getSingletonInstance(){    static Singleton instance;    return &instance;}

In C++03, a common approach was to use double-checked locking; checking a flag (or the pointer itself) to see if the object might be uninitialised, and only locking the mutex if it might be. This requires some kind of non-standard way of atomically reading the pointer (or an associated boolean flag); many implementations incorrectly use a plain pointer or bool, with no guarantee that changes on one processor are visible on others. The code might look something like this, although I've almost certainly got something wrong:

static Singleton* getSingletonInstance(){    if (!atomic_read(singletonInstance)) {        mutex_lock lock(mutex);        if (!atomic_read(singletonInstance)) {            atomic_write(singletonInstance, new Singleton);        }    }    return singletonInstance;}

This is quite tricky to get right, so I suggest that you don't bother. In C++11, you could use standard atomic and mutex types, if for some reason you want to keep the dynamic allocation of you example.

Note that I'm only talking about synchronised initialisation, not synchronised access to the object (which your version provides by locking the mutex in the accessor, and releasing it later via a separate function). If you need the lock to safely access the object itself, then you obviously can't avoid locking on every access.


As @piokuc suggested, you can also use a once function here. If you have C++11:

#include <mutex>static void init_singleton() {    singletonInstance = new Singleton;}static std::once_flag singleton_flag;Singleton* getSingletonInstance() {    std::call_once(singleton_flag, init_singleton);    return singletonInstance;}

And, yes, this will work sensibly if the new Singleton throws an exception.


If you have C++11 you can make singletonInstance an atomic variable, then use a double-checked lock:

if (singletonInstance == NULL) {    lock the mutex    if (singletonInstance == NULL) {        singletonInstance = new Singleton;    }    unlock the mutex}return singletonInstance;