The article directories

    • The singleton pattern
    • Code implementation
    • Ascending part
      • Multithreaded singleton mode
      • Hangry singleton
      • Lazy or hungry?
      • Advantages and disadvantages of the singleton pattern

The singleton pattern

What is the singleton pattern? In the project, there are classes that need to be “planned”, that is, the class can only have one instance, and there is a risk of data inconsistency if there are more than one instance.

Singleton pattern: Ensure that a class has only one instance and provide a global access point to access it.

The class of this pattern is called a singleton class, so I won’t draw the class diagram. Example of application scenario of singleton mode: When it comes to data problems, the database is the first to be affected, and the cache will not escape naturally.


Code implementation

// Here is the.h file
// Boss singleton
class Single_Boss
{
public:
    static Single_Boss *instence(a);// Get the database singleton
// Focus on this function
	void run(a);
private:
    Single_Boss(a); ~Single_Boss(a);char *errmsg;

    static Single_Boss *Boss;/ / instance
};
Copy the code
/ / the source file

Single_Boss *Single_Boss::Boss= NULL;

Single_Boss::Single_Boss()
{
    cout << "Big Boss" << endl;	//debug
}

Single_Boss::~Single_Boss()
{
    cout<<"Seeyou Boss"<<endl;
}

Single_Boss* Single_Boss::instence(a)
{
    if(! Boss) { Boss=new Single_Boss(a); }return Boss;
}

void Single_Boss::run(a){
	cout<<"Hello, welcome to XXX, may I help you?"<<endl;
}

int main(a)
{
	//Single_Boss *boss = new Single_Boss(); // If you don't believe me, you can put this line out, and try masking the following line
    Single_Boss *boss= Single_Boss::instence(a);// This is using singletons outside the class
    
    boss->run(a);return 0;
}
Copy the code

Ascending part

Multithreaded singleton mode

Once there was a sincere database in front of me, but UNFORTUNATELY I did not cherish it. Until my project crashed repeatedly, I did not know that if I could do it again, I would add a lock…

All past, the number of romantic figures, but also look at today.

Let’s revisit the following code:

Single_Boss* Single_Boss::instence(a)	/ / 1
{										
    if(! Boss)/ / 2
    {									
        Boss= new Single_Boss(a);/ / 3
    }									
    return Boss;						
}										
Copy the code

What if, in the multi-threaded case, once two threads enter 2 at the same time? Isn’t that perfectly normal? There’s no defense. Isn’t that a head shot? White to!!!!!

So, change it:

Single_Boss* Single_Boss::instence(a)	/ / 1
{					
	lock(db_mutex);	// Suppose I initialized the lock already
    if(! Boss)/ / 2
    {									
        Boss= new Single_Boss(a);/ / 3
    }				
    unlock(db_mutex);	// Lock and unlock must be written at the same time, even if you forget to write intermediate steps, you must write unlock first
    
    return Boss;						
}	
Copy the code

That’s a good way to write it, right? B: Sure.

You can also add another layer like this, which is better:

Single_Boss* Single_Boss::instence(a)	/ / 1
{				
	if(! Boss){// Re-lock
		lock(db_mutex);				
	    if(! Boss)// Double lock
	    {									
	        Boss= new Single_Boss(a); }unlock(db_mutex);	// Lock and unlock must be written at the same time, even if you forget to write intermediate steps, you must write unlock first
    }
    return Boss;						
}
Copy the code

This is the lazy singleton.

Hangry singleton

What is hangry? The key to hangry mode: initialization is instantiation

Fine-tune the code above:

Single_Boss *Single_Boss::Boss= new Single_Boss(a);Single_Boss* Single_Boss::instence(a)
{
// No instantiation is required
    //if(! Boss)
    / / {
    // Boss= new Single_Boss();
    / /}
   	return Boss;
}
Copy the code

The downside of normal hungry loading is that maybe I don’t want to use an instance but it’s already constructed, which is a waste of memory as opposed to lazy loading, but it’s easy to implement.

Lazy or hungry?

Which one to choose depends on your personal preference. Here are some suggestions:

Lazy: in the traffic is small, using lazy to achieve. It's time for space. Hungry: Because thread synchronization is required, better performance can be achieved by using hungry when there are a large number of visits or a large number of threads that may be accessed. This is space for time.Copy the code

Advantages and disadvantages of the singleton pattern

advantages

Because the singleton pattern has only one object in memory, it reduces the memory expense, especially when the object needs to be created and destroyed frequently, and the performance cannot be optimized during creation or destruction, the singleton pattern has obvious advantages. The singleton pattern avoids multiple footprint of memory. The singleton pattern allows you to set up global access points in the system to optimize and share resource access. I often use this trick, and also like it, because it is really convenient, do a flag bit singleton class, responsible for all the data table mapping processing. (To understand can be private message me)Copy the code

disadvantages

Singleton mode generally has no interface and is difficult to expand. If you want to expand, consider refactoring. The singleton pattern is bad for testing. In a concurrent environment, you cannot test if the singleton is not completed.Copy the code