Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Singleton with multithreads

Tags:

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?

like image 941
madu Avatar asked Sep 03 '12 13:09

madu


People also ask

How would you handle a singleton in a multi threaded environment?

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.

Can we implement multithreading in singleton class?

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 a singleton class thread-safe?

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.

Should you avoid singletons?

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.


2 Answers

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.

like image 114
Mike Seymour Avatar answered Jan 17 '23 15:01

Mike Seymour


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.

like image 26
Pete Becker Avatar answered Jan 17 '23 14:01

Pete Becker