1 single-instance patterns in textbooks
We all know how a simple singleton pattern should be implemented: the constructor is declared as private or protect to prevent being instantiated by an external function, and a private static class pointer is stored inside a unique instance, and the action of the instance is handled by a public class method. The method also returns an instance of the Singleton class.
On the code:
Class Singleton{protected:singleton () {}private:static singleton* p;public:static singleton* instance ();}; singleton* Singleton::p = null;singleton* singleton::instance () {if (p = = NULL) p = new Singleton (); return p;}
This is a great implementation, easy to understand. But is this a perfect realization? No! This method is thread insecure, considering that two threads are simultaneously calling the instance method at the same time and detecting that p is a null value at the same time, two threads will construct an instance to p at the same time, which is a serious error! At the same time, this is not the only implementation of the Singleton!
2 lazy and a hungry man
There are about two implementations of the Singleton: The lazy and the A hungry man.
-
- Lazy: So the name of righteousness, not to the last resort to instantiate the class, that is, the first time to use the class instance will be instantiated, so the classic method above is classified as lazy realization;
- A hungry man: you must be hungry. Therefore, it is instantiated when the Singleton class is defined.
Features and options:
-
- Because of the thread synchronization, it is possible to achieve better performance by using a hungry man implementations when the traffic is large, or the number of threads that may be accessed is relatively high. It is time to change space.
- When the traffic is small, the use of lazy to achieve. It is time to change space.
3 Thread-Safe lazy implementations
Thread is not secure, how to do? The most intuitive method: lock.
- Method 1: Lock the classic lazy implementation:
Class Singleton{protected:singleton () {pthread_mutex_init (&mutex);} Private:static singleton* p;public:pthread_mutex_t mutex;static singleton* initance ();}; singleton* Singleton::p = null;singleton* singleton::initance () {if (p = = NULL) {pthread_mutex_lock (&mutex); if (p== NULL) p = new Singleton ();p Thread_mutex_unlock (&mutex);} return p;}
- Method 2: Lazy implementation of internal static variables
This method is also very easy to implement, in the instance function to define a static instance, can also be guaranteed to have a unique instance, on return only need to return its pointer on it. It's really very simple to recommend this implementation method.
Class Singleton{protected:singleton () {pthread_mutex_init (&mutex);} public:pthread_mutex_t mutex;static singleton* initance (); int A;}; singleton* singleton::initance () {pthread_mutex_lock (&mutex); static Singleton Obj;pthread_mutex_unlock (& Mutex); return &obj;}
4 A Hungry man implementation
Why don't I say "thread-safe a hungry man implementation"? Because the A hungry man implementation is inherently thread-safe, no locking is necessary. Why? Think for yourself!
Class Singleton{protected:singleton () {}private:static singleton* p;public:static singleton* initance ();}; singleton* Singleton::p = new singleton;singleton* singleton::initance () {return p;}
Is it particularly simple?
With space to change time, you say simple is not simple?
How does a thread-safe singleton pattern be written during an interview? Must be how simple how to write! A hungry man mode is the most lazy [ serious face ]!
Singleton mode and thread-safe singleton mode for C + + (lazy/a hungry man)