Singleton Instance Declared as Static Variable of Getinstance Method, Is It Thread-Safe

Singleton instance declared as static variable of GetInstance method, is it thread-safe?

In C++11 it is thread safe:

§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.

In C++03:

  • Under g++ it is thread safe.

    But this is because g++ explicitly adds code to guarantee it.

One problem is that if you have two singletons and they try and use each other during construction and destruction.

Read this:
Finding C++ static initialization order problems

A variation on this problem is if the singleton is accessed from the destructor of a global variable. In this situation the singleton has definitely been destroyed, but the get method will still return a reference to the destroyed object.

There are ways around this but they are messy and not worth doing. Just don't access a singleton from the destructor of a global variable.

A Safer definition but ugly:

I am sure you can add some appropriate macros to tidy this up

SomeBaseClass &SomeClass::GetInstance()
{
#ifdef _WIN32
Start Critical Section Here
#elif defined(__GNUC__) && (__GNUC__ > 3)
// You are OK
#else
#error Add Critical Section for your platform
#endif

static SomeClass instance;

#ifdef _WIN32
END Critical Section Here
#endif

return instance;
}

Singleton instance as static field vs. static variable in getInstance() method


What are these trade-offs?

This is the most important consideration:

The static data member is initialized during the static initialization at the start of the program. If any static object depends on the singleton, then there will be a static initialization order fiasco.

The function local static object is initialized when the function is first called. Since whoever depends on the singleton will call the function, the singleton will be appropriately initialized and is not susceptible to the fiasco. There is still a - very subtle - problem with the destruction. If a destructor of a static object depends on the singleton, but the constructor of that object does not, then you'll end up with undefined behaviour.

Also, being initialized on the first time the function is called, means that the function may be called after the static initialization is done and main has been called. And therefore, the program may have spawned multiple threads. There could be a race condition on the initialization of the static local, resulting in multiple instances being constructed. Luckily, since C++11, the standard guarantees that the initialization is thread safe and this tradeoff no longer exists in conforming compilers.

Thread safety is not an issue with the static data member.

Which approach is better?

That depends on what your requirements are and what version of the standard you support.

Is Meyers' implementation of the Singleton pattern thread safe?

In C++11, it is thread safe. According to the standard, §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.

GCC and VS support for the feature (Dynamic Initialization and Destruction with Concurrency, also known as Magic Statics on MSDN) is as follows:

  • Visual Studio: supported since Visual Studio 2015
  • GCC: supported since GCC 4.3

Thanks to @Mankarse and @olen_gam for their comments.


In C++03, this code wasn't thread safe. There is an article by Meyers called "C++ and the Perils of Double-Checked Locking" which discusses thread safe implementations of the pattern, and the conclusion is, more or less, that (in C++03) full locking around the instantiating method is basically the simplest way to ensure proper concurrency on all platforms, while most forms of double-checked locking pattern variants may suffer from race conditions on certain architectures, unless instructions are interleaved with strategically places memory barriers.

Is this code correct example of thread safe Singleton design pattern?

This is guaranteed to be safe by the JLS. See the holder pattern: "since the class initialization phase is guaranteed by the JLS to be sequential, i.e., non-concurrent, no further synchronization is required in the static getInstance method during loading and initialization."

The holder pattern is more complex than what you want, but the important part is that static final Something INSTANCE = new Something() is safe no matter which class it is declared in. The benefit of the holder pattern compared to what you have is that the singleton won't be initialized until the first time it is used. This is helpful if you want to access other static members in your Singleton class when the cost of initializing the Singleton instance is expensive.

As Lewis_McReu and user6690200 pointed out, you should declare the INSTANCE field final in order to ensure that you don't accidentally assign a different Singleton instance to the variable. You should also declare a private no-argument Singleton() constructor to prevent other instances from being created. To make it even more bulletproof, you should declare the Singleton class final so that you can't subclass it with a public constructor.

C++ Singleton design pattern

In 2008 I provided a C++98 implementation of the Singleton design pattern that is lazy-evaluated, guaranteed-destruction, not-technically-thread-safe:

Can any one provide me a sample of Singleton in c++?

Here is an updated C++11 implementation of the Singleton design pattern that is lazy-evaluated, correctly-destroyed, and thread-safe.

class S
{
public:
static S& getInstance()
{
static S instance; // Guaranteed to be destroyed.
// Instantiated on first use.
return instance;
}
private:
S() {} // Constructor? (the {} brackets) are needed here.

// C++ 03
// ========
// Don't forget to declare these two. You want to make sure they
// are inaccessible(especially from outside), otherwise, you may accidentally get copies of
// your singleton appearing.
S(S const&); // Don't Implement
void operator=(S const&); // Don't implement

// C++ 11
// =======
// We can use the better technique of deleting the methods
// we don't want.
public:
S(S const&) = delete;
void operator=(S const&) = delete;

// Note: Scott Meyers mentions in his Effective Modern
// C++ book, that deleted functions should generally
// be public as it results in better error messages
// due to the compilers behavior to check accessibility
// before deleted status
};

See this article about when to use a singleton: (not often)

Singleton: How should it be used

See this two article about initialization order and how to cope:

Static variables initialisation order

Finding C++ static initialization order problems

See this article describing lifetimes:

What is the lifetime of a static variable in a C++ function?

See this article that discusses some threading implications to singletons:

Singleton instance declared as static variable of GetInstance method, is it thread-safe?

See this article that explains why double checked locking will not work on C++:

What are all the common undefined behaviours that a C++ programmer should know about?

Dr Dobbs: C++ and The Perils of Double-Checked Locking: Part I

safe way to get a singleton instance from multithreads

1.You do need to guard it and even if you don't, of course, OS wouldn't do it for you. Use following code for thread-safety:

DataCenter* DataCenter::getInstance()
{
MutexLocker locker(DataCenter::m_mutex);
if(!m_instanceFlag)
{
m_instance = new DataCenter();
m_instanceFlag = true;
}
return m_instance;
}

Edit:

Where MutexLocker is something like this:

class MutexLocker
{
pthread_mutex_t &mutex;
public:
MutexLocker(pthread_mutex_t &mutex):mutex(mutex)
{
if(pthread_mutex_lock(&this->mutex)!=0)
throw std::runtime_error("mutex locking filed");
}
~MutexLocker(void)
{
if(pthread_mutex_unlock(&this->mutex)!=0)
throw std::runtime_error("mutex unlocking filed");
}
}

2.First method looks ok, but not thread-safe.

Why the singleton works here, although a static variable is re-initialized to NULL?


I expected that the instance was re-initialzed to NULL everytime.

No, static variables are only initialised once, the first time the program reaches the definition (or earlier if, as here, it can be statically initialised).

Of course, you've got a memory leak, and the object creation isn't thread-safe; but this isn't the place for yet another essay about the perils of the Singleton anti-pattern.

c++: is this getInstance() method of my singleton threadsafe?

Since each entry to the function will create its own lock, the lock will be completely useless; any number of threads can enter the function, lock different locks, and start messing with the static data at the same time.

You could create the lock at file (or class static) scope; this would ensure it's created in time, provided that you don't start threads before main(). However, this would also serialize entry to the function even after the static data is initialized.

Why not just define your static data at file (or class static) scope in the first place?



Related Topics



Leave a reply



Submit