C++: 05. Singleton mode

singleton pattern

A class can only be instantiated once, producing an object.

In a class, to construct an instance, you need to pass the constructor, so in order to prevent the instance from being constructed by calling the constructor of the class externally, you need to mark the access permission of the constructor as protected or private;

And if it needs to be provided to the global access point, a static function needs to be defined in the class to return the uniquely constructed instance inside the class.

Lazy style: The class instance will be instantiated when it is used for the first time. When the number of visits is small, the lazy style is used to trade time for space. It is not safe , because instantiation is not an atomic operation. During the instantiation process, before assigning a value to the pointer, the cpu switches threads and generates multiple objects.

Hungry Chinese style: instantiate when the singleton class is defined. When the number of visits is large and there are many threads, the Hungry Chinese style is adopted, and space is exchanged for time. Thread- safe because it is instantiated in the first place.

懒汉式:
class Single           
{                            
public:
	static pthread_mutex_t mtx;   互斥锁

***************在饿汉式中该函数只需要一个return***************
	static Single* get_Single()
	{
		if (p == NULL)  双重检查
		{
			pthread_mutex_lock(&mtx);
			if (p == NULL)  多线程,需要加锁,保证其他线程无法获取锁而阻塞。
                                        如果不加锁,又因为实例化不是原子操作,导致可能有多个进程创建多个对象
			{
				p = new Single;  如果还没有唯一的对象就先生成,实例化,不是原子操作
			}
			pthread_mutex_unlock(&mtx);
		}
		return p;
	}
private:
	static Single* volatile p;
	Single(){}
};
pthread_mutex_t Single::mtx = PTHREAD_MUTEX_INITIALIZER;  创建互斥锁

***************懒汉与饿汉的区别就在于这个静态成员变量实例化的位置不一样***************
Single* Single::p = NULL;  静态成员变量初始化       懒汉式在此处实例化
 
int main()
{
	Single* tmp = Single::get_Single();  用作用域加成员函数名调用静态函数。
	Single* tmp1 = Single::get_Single(); 
	cout <<tmp <<endl<<tmp1<<endl;
	return 0;
}

Solve several problems:

1. Why use static functions and static member variables?

To call a function in a class, you need to construct an object first, and then you can call member methods in the class with an object. But this method is definitely not suitable for singleton mode. The other method is a static function, which can be called directly using the class name. Static functions can only call static member methods.

2. Why double check?

Let's analyze from the inside out. First, in order to meet the requirements of the singleton mode, that is to say, p creates an object, and then it can no longer be created. A layer of judgment needs to be added outside to ensure that the singleton can be successfully implemented in the case of a single thread. . But this is only satisfied under a single thread. If there are multiple threads, due to the rotation of the CPU time slice, it is likely to be truncated during the assignment to p, so that another process also creates an object. To avoid this, it needs to be in Add a mutex outside. But the locking operation is done by the kernel, which means that every time you check whether the lock is held, you need to fall into the kernel. In this case, we found that it is unfriendly to single-threaded, and there is no need for single-threaded to take locks and unlock to consume time and resources. So we added the outermost layer of judgment. If p is not NULL, we skip it directly and no longer perform lock operations.

3. What is a private static member variable volatile?

volatile:

1. Prevent multiple threads from performing thread cache operations on shared variables. If one thread modifies the shared variable, the other thread cannot see it in time.

Explain: In addition to the space on the cpu register and the memory, there is also a cache buffer area between the two. Multi-thread shared variables cache a copy of the data on the thread stack. As a result, the cpu is taking the second when an instruction is given. Misunderstanding that the p pointer has not been instantiated.

2. Prevent the compiler from reordering codes involving value operations

Guess you like

Origin blog.csdn.net/qq_41214278/article/details/83718210