当前位置:网站首页>Creative mode 1 - single case mode
Creative mode 1 - single case mode
2022-07-05 23:13:00 【Dutkig】
After learning C++ Knowledge about static members of , Let's first understand the simplest design pattern : The singleton pattern .
The motivation of the singleton model
For some classes of a software system , There is no need to create multiple instantiated objects , Like Windows System task manager or recycle bin , No matter how many times we click, only one window will pop up , Because if multiple windows pop up , It's actually a repeating object , It is bound to waste system resources , Therefore, we need to ensure that there is only one instance of a class in the system , When this instance is created successfully , We can no longer create other objects of the same type , All operations can only be based on this unique instance , For example, ensure the uniqueness of objects , We propose a singleton pattern .
From the perspective of concrete implementation :
- Singleton mode only provides private constructors ;
- The class definition contains a static private object of the class ;
- This class provides a static common function to create or obtain its own static private object .
1、 The hungry man mode
An example of the hungry man model is The main function has been generated before it runs ( This is because the initialization of static data members is completed before the main function runs ), Because it's hungry , Very anxious .^ _ ^…
class Object
{
private:
int value;
static Object instance;
private:
Object(int x = 0):value(x){
}// Objects cannot be built outside anywhere else
Object(const Object & obj) = delete;// Prevent copying construction objects
Object & operator=(const Object & obj) = delete;// Prevent building objects through assignment statements
public:
static Object & GetInstance()// If you do not return by reference here, you will transfer the copy structure as a transition
{
// But our copy structure has been deleted , Unable to complete . Another solution is to return with a pointer
return instance;
}
};
// Static member initialization
Object Object::instance();
int main()
{
Object & obja = Object::GetInstance();
Object & objb = obja.GetInstance();
cout<<&obja<<endl;
cout<<&objb<<endl;
}
We can see ,obja and objb All represent the same object :
Be careful : The above way Objects created : yes Thread safety Of , When two threads modify it respectively , It's not thread safe .
such as : Put the following two functions into two threads
void funa()
{
Object & obja = Object::GetInstance();
cout<<&obja<<endl;
}
void funb()
{
Object & objb = Object::GetInstance();
cout<<&objb<<endl;
}
#include<thread>
int main()
{
thread thra(funa);
thread thrb(funb);
thra.join();
thrb.join();
return 0;
}
No matter how many threads call , When building objects, we all get unique instantiated objects
summary :
experience : Why should we define this design pattern as hungry man singleton pattern ?
namely : Like a hungry man , Create instances whether you need them or not , That is, create a good instance when the class is generated , This is a practice of exchanging space for time . As a hungry man , Embodies its essence ——“ All I want ”.
- advantage : Instantiate when the program is loaded , After that, the operation efficiency will be higher
- shortcoming : Because the program is instantiated when it is loaded , If there is no further operation on this class , Will lead to a waste of memory .
Lazy singleton mode
An example of lazy mode is lazy , So only when someone wants to use an instance new, Have to build .
class Object
{
private:
int value;
static Object *pobj;
private:
Object(int x = 0):value(x){
}
Object(const Object & obj) = delete;
Object & operator=(const Object & obj) = delete;
public:
static Object * GetInstance()
{
if(pobj == nullptr)
{
pobj = new Object();
}
return pobj;
}
};
// Static member initialization
Object* Object::pobj = nullptr;
void funa()
{
Object * pobja = Object::GetInstance();
cout<<pobja<<endl;
}
void funb()
{
Object * pobjb = Object::GetInstance();
cout<<pobjb<<endl;
}
int main()
{
thread thra(funa);
thread thrb(funb);
thra.join();
thrb.join();
return 0;
}
In our opinion, even if the running result is ok , But this code is actually thread unsafe .
Because there have been many object constructions , This is inconsistent with the original principle of the simple interest single case model
Explain in detail :
In a single thread , This kind of writing can be used correctly , But not in multithreading , This method is thread unsafe .
(1) If a thread A And thread B, These two threads need to access getInstance function , Threads A Get into getInstance function , And detect if Conditions , Because it is the first time to enter ,value_ It's empty ,if Conditions established , Ready to create an object instance .
(2) however , Threads A It's possible to be OS The scheduler of is interrupted and sleep is suspended , And give control to the thread B.
(3) Threads B Also came to if Conditions , Find out value_ Still for NULL, Because the thread A It was interrupted before it could be constructed . At this point, suppose the thread B Finished creating the object , And return smoothly .
(4) After that thread A Awakened , Carry on new Create the object again , thus , Two threads build two object instances , This destroys uniqueness .
in addition , There are also memory leaks ,new What comes out has never been released
So how to solve this problem ??—— Join in Thread mutex
#include<mutex>
std::mutex mtx;// Build a lock object
class Object
{
private:
int value;
static Object* pobj;
private:
Object(int x = 0) :value(x) {
}
Object(const Object& obj) = delete;
Object& operator=(const Object& obj) = delete;
public:
static Object* GetInstance()
{
if (pobj == nullptr)
{
lock_guard<std::mutex> lock(mtx);
if (pobj == nullptr)// Judge again , Ensure that multiple threads will not enter at the same time during locking
{
pobj = new Object(10);
}
}
return pobj;
}
};
// Static member initialization
Object* Object::pobj = nullptr;
At this time, we found that : The problem is really solved 
Actually , At present, the lazier style is more popular, and the following one is more concise Writing : it Take advantage of static Keyword features .
class Object
{
private:
int value;
static Object* pobj;
private:
Object(int x = 0) :value(x) {
}
Object(const Object& obj) = delete;
Object& operator=(const Object& obj) = delete;
public:
static Object* GetInstance()
{
static Object instance;
return &instance;
}
};
This is thread safe , Because this instance allocates memory in the global data area , The object is initialized only once when it is created , Go deeper The explanation is : Compiler for static Initialization of static local variables , It will automatically lock and unlock .
experience : Why should we define this design pattern as lazy singleton pattern ?
namely : Like a lazy man , You need to use the program to create instances , You don't need to create an instance program “ Don't bother ” To create instances , This is a time for space approach , This is reflected. “ Lazy nature ”.
边栏推荐
- [screen recording] how to record in the OBS area
- 两数之和、三数之和(排序+双指针)
- Leetcode buys and sells stocks
- openresty ngx_ Lua request response
- The PNG image is normal when LabVIEW is opened, and the full black image is obtained when Photoshop is opened
- 数据库基础知识(面试)
- 视频标准二三事
- 一文搞定class的微觀結構和指令
- Three.js-01 入门
- 2022 registration examination for safety management personnel of hazardous chemical business units and simulated reexamination examination for safety management personnel of hazardous chemical busines
猜你喜欢

Mathematical formula screenshot recognition artifact mathpix unlimited use tutorial

Alibaba Tianchi SQL training camp task4 learning notes
![Development specification: interface unified return value format [resend]](/img/3e/8751b818147cabbe22e4ce44af7d24.jpg)
Development specification: interface unified return value format [resend]

数学公式截图识别神器Mathpix无限使用教程

Registration of Electrical Engineering (elementary) examination in 2022 and the latest analysis of Electrical Engineering (elementary)

Hcip day 11 (BGP agreement)

openresty ngx_lua请求响应

Go语言实现原理——锁实现原理

2022 R2 mobile pressure vessel filling review simulation examination and R2 mobile pressure vessel filling examination questions
![[speech processing] speech signal denoising and denoising based on MATLAB low-pass filter [including Matlab source code 1709]](/img/f4/4d09dc05f5789b980ebd23cc352f8b.jpg)
[speech processing] speech signal denoising and denoising based on MATLAB low-pass filter [including Matlab source code 1709]
随机推荐
Global and Chinese market of diesel fire pump 2022-2028: Research Report on technology, participants, trends, market size and share
[screen recording] how to record in the OBS area
Activate function and its gradient
Openresty ngx Lua regular expression
From the perspective of quantitative genetics, why do you get the bride price when you get married
Krypton Factor purple book chapter 7 violent solution
TOPSIS code part of good and bad solution distance method
How to quickly understand complex businesses and systematically think about problems?
Detailed explanation of pointer and array written test of C language
一文搞定class的微觀結構和指令
Three.JS VR看房
leecode-学习笔记
3: Chapter 1: understanding JVM specification 2: JVM specification, introduction;
Marginal probability and conditional probability
February 13, 2022 -5- maximum depth of binary tree
Registration and skills of hoisting machinery command examination in 2022
透彻理解JVM类加载子系统
Leetcode sword finger offer brush questions - day 21
Leecode learning notes
Leetcode daily question 1189 The maximum number of "balloons" simple simulation questions~



