This question was asked in an interview. The first part was to write the singleton class:
class Singleton { static Singleton *singletonInstance; Singleton() {} public: static Singleton* getSingletonInstance() { if(singletonInstance == null) { singletonInstance = new Singleton(); } return singletonInstance; } };
Then I was asked how to handle this getSingletonInstance()
in a multithreaded situation. I wasn't really sure, but I modified as:
class Singleton { static Singleton *singletonInstance; Singleton() {} static mutex m_; public: static Singleton* getSingletonInstance() { m_pend(); if(singletonInstance == null) { singletonInstance = new Singleton(); } return singletonInstance; } static void releaseSingleton() { m_post(); } };
Then I was told that although a mutex is required, pending and posting a mutex is not efficient as it takes time. And there is a better way to handle to this situation.
Does anybody know a better and more efficient way to handle the singleton class in a multithreaded situation?
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.
While we are using multithreading access to a singleton instance can be performed from various threads it could be a problem while constructing singleton instances. If you are in Singleton::Instance() and receive an interrupt, invoke Singleton::Instance() from another thread, you can see how you'd get into trouble.
Is singleton thread safe? A singleton class itself is not thread safe. Multiple threads can access the singleton same time and create multiple objects, violating the singleton concept. The singleton may also return a reference to a partially initialized object.
The truth is that singletons aren't inherently bad if they're used correctly. The goal of the singleton pattern is to ensure only one instance of a class is alive at any one time. That, however, is not the goal many developers have in mind when using singletons.
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 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