当前位置:网站首页>Sword finger offer (I) -- handwriting singleton mode
Sword finger offer (I) -- handwriting singleton mode
2022-07-02 20:35:00 【Qinhuai grocery store】
The finger of the sword Offer The first question of : How to write a singleton code ?
1. What is the singleton pattern ?
The singleton pattern , It's a relatively simple design pattern , It's also a creative model ( Provides a pattern or way to create objects ). The main points of : 1. Involving a single class , This class creates its own objects ( The creation method cannot be overridden elsewhere , When initializing a class, create or provide private methods to access or create , You have to make sure that only a single object is created ). 2. Singleton mode is not necessarily thread unsafe . 3. Singleton patterns can be divided into two types :
The sluggard model ( Create the class the first time you use it , It can be understood that the class is very lazy when loading , Get it only when you need it , If not, create , Because it's a single case , So it's only the first time you use it , Once created, you can always use the same object ). Starving model ( It was created when the class was loaded , It can be understood that the hungry man has been hungry and thirsty , You must hold the resources in your own hands first , So when the class is loaded, the instance will be created first , The same example will be used later )
Keywords used :
- Single case :singleton
- example :instance
- Sync : synchronized
- Guaranteed visibility :volatile
2. Why use singleton mode ?
Singleton mode is to control the number of instances , At the same time, it saves the resources of the system , If we want only one object in a class in the system , Consider using singleton mode . for instance : our windows System , Those applications, such as Netease cloud music client , Click on the open , It's an interface , Let's minimize this window , Click client again to open , We found that it was still the original interface , It doesn't recreate an interface . I don't want to waste system resources , Using the idea of singleton pattern . If it hasn't been opened yet , Just create a new interface ( It's actually a process ) Show , If it's already turned on , Will use the previous , It won't reopen the same .
3. What are the advantages and disadvantages of singleton mode ?
- advantage :
- Guaranteed only one instance , If the instance of this class takes up a lot of resources ( Heavyweight objects ), Then we can save resources to a great extent , To save memory , Saves time creating objects frequently , Make sure that every object is unique instance.
- shortcoming :
- Not applicable to changed objects , Because there's only one instance , If the data keeps changing , Then it is likely to cause data errors in different scenarios , To the extreme , Different threads use this instance , Change its value , Then there's the possibility of something wrong .
- Every time you make a judgment to check whether the instance already exists , This is also an expense , But it's tiny , It can also be initialized statically ( Starving model ) To solve .
4. What are the usages of singleton pattern ? How to write is a single example ?
The singleton model is mainly lazy , Hungry Chinese style , Enumeration , And registration , Of course, there are other , Here are some common ones that we often know or use . We all know that the purpose of singleton is : In order to have only one instance of the class used elsewhere . It can be said less rigorously that , To achieve this goal, the idea involved is a singleton .
Starving model (2 Kind of ):
Starving mode means that the instantiation is completed when the class is initialized, that is, loaded . advantage : Relatively simple , Because it was initialized at the beginning , There will be no thread safety issues when creating , There won't be two instances created . shortcoming : The instantiation is completed when the class is loaded , If this class depends on more resources , That is, if this class is a heavy object , Class loading takes a long time , If not used , That would be a waste of resources .
1.public modification , The starvation mode of direct access
The first one is single yes public, You can go directly through Singleton Class name
public class Singleton { // Privatized construction method , To prevent the outside world from using this construction method to create new instances private Singleton(){ } // The default is public, Access can be made directly through Singleton.instance To visit static Singleton instance = new Singleton(); }
2.private modification , Starvation mode accessed through method
The second is to use private modification singleton, Then we need to provide static Method to access .
public class Singleton { private Singleton(){ } // Use private modification , Then we need to provide get Methods for external access private static Singleton instance = new Singleton(); //static Categorize methods into all , Directly through the class name to access public static Singleton getInstance(){ return instance;. } }
Starving model , There is no problem in this way of writing , There will be no thread safety issues , But there are shortcomings , because instance The initialization of is in progress when the class is loaded , So class loading is done by ClassLoader To achieve , The advantage of initialization earlier is that it can be directly used later , The disadvantage is that resources are wasted , If only individual classes use this method , It depends on less data , So this method is also a better singleton method . In singleton mode, it's usually called getInstance() Method to trigger class loading , Obviously, the above two starvation modes have not been realized lazyload( Personal understanding means that class loading is triggered only when it is used )
3. Improved , Lazy and hungry mode
Here's an improved version of the hungry man model , utilize Inner class Implement lazy loading in this way Singleton Class is loaded , however instance It doesn't have to be initialized , Wait until the SingletonHolder When it's actively used , That is to call... Explicitly getInstance Method time , Will be loaded explicitly SingletonHolder class , To instantiate instance. This method uses class loader to ensure that only one thread can initialize instance, So it ensures that the single instance , And realized lazy loading . The static inner class ensures the thread safety of single instance under multithreading concurrency , But when you encounter a serialized object , Running in the default mode will result in multiple instances .
public class Singleton { private Singleton(){ } // Inner class private static class SingletonHolder{ private static final Singleton instance = new Singleton(); } // Get methods that are not allowed to be rewritten public static final Singleton getInstance(){ return SingletonHolder.instance; } }
The sluggard model (2 Kind of ):
The most basic code ( Thread unsafe ):
public class Singleton { private static Singleton instance = null; private Singleton(){ } public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
This kind of writing , Every time you get an instance instance Is to judge , If not, then new One came out , Otherwise, it will directly return to the existing instance. But this way of writing Not thread safe , When more than one thread happens to execute getInstance() Method time , Judge whether it is equal to null When , Each creates a new instance , In this way, the singleton cannot be guaranteed . So we're going to think of synchronous locks , Use synchronized keyword : Add synchronization lock code ( Thread safety , The efficiency is not high )
public class Singleton { private static Singleton instance = null; private Singleton() {} public static Singleton getInstance() { synchronized(Singleton.class){ if (instance == null) instance = new Singleton(); } return instance; } }
In this case ,getInstance() The method will be locked , When two threads access this method at the same time , There will always be a thread that gets the synchronization lock first , Then the thread can be executed , And the other thread has to wait , Wait for the first thread to finish executing getInstance() After method , To execute . This code It's thread safe , But it's not efficient , Because if there are a lot of threads , Then you have to make all the threads waiting to be accessed , This will Greatly reduced efficiency . So we have an idea that , Reduce the probability of lock occurrence , That's what we call double check ( Double check lock ).
public class Singleton { private static Singleton instance = null; private Singleton() {} public static Singleton getInstance() { if (instance == null){ synchronized(Singleton.class){ if (instance == null) instance = new Singleton(); } } return instance; } }
1. first if Judge , To reduce the probability of lock occurrence , The previous code , As long as the same method is executed, the lock will be triggered , And only here singleton It will trigger when it is empty , The so-called double check , The first check is not thread safe , That is to say, multiple threads may get singleton by null Result , The next synchronization block ensures that only one thread enters at the same time , And the first thread that enters creates the object , When other threads re-enter, the object has been created and will not continue to be created . It's a very clever way , If you synchronize the entire method , All threads that get singletons are queued , Efficiency will be reduced . But in fact, we only need to synchronize the creation process to ensure ” Single case ”, Multiple threads can request at the same time regardless of whether there is a singleton .
2. the second if Judgment is the same as the previous code .
The above code seems to have no problem , in fact , And there's a very small probability that something goes wrong , So let's first understand : Atomic manipulation , Command rearrangement .
1. Atomic manipulation
- Atomic manipulation , It can be understood as an indivisible operation , It is too small to be split into multiple operations , So in a computer, either it's fully executed , Or it's not implemented at all , It doesn't exist, it's executed to an intermediate state , There is no intermediate state . such as : An assignment statement is an atomic operation :
n = 1; // This is an atomic operation
hypothesis n The value of was 0, So behind this operation is either successful execution n be equal to 1, Or it didn't work n be equal to 0, There will be no intermediate state , Even in the concurrent process, it's the same . Let's look at a sentence It's not an atomic operation Code for :
int n =1;// It's not an atomic operation
reason : This statement can be split into two operations 1. Declare variables n 2. Assign the variable to 1 We can see from it that there is a state of n The state of being declared but not assigned in time , In this case , In concurrency , If multiple threads are used at the same time n, Then it may lead to unstable results .
2. Command rearrangement
So called command rearrangement , The computer will optimize our code , In the process of optimization, without affecting the final result , Adjusting the order of atomic operations . Consider the following code :
int a ; // sentence 1 a = 1 ; // sentence 2int b = 2 ; // sentence 3int c = a + b ; // sentence 4
Normal situation , The order of execution should be 1234, But it could actually be 3124, perhaps 1324, That's because the statement 3 and 4 There's no atomic problem , Then it could be split into atomic operations , And then rearrange it . The basic understanding of atomic operations and instruction rearrangement ends here , Look back at our code :
Mainly instance = new Singleton(), According to what we say , This statement is not an atomic operation , Then it will be split , in fact JVM(java virtual machine ) The operation on this statement : 1. to instance Allocated memory 2. call Singleton The constructor for initializes a member variable , There are examples , Put it in another memory space 3. take instance Object points to the allocated memory space , It's only after this step is really completed ,instance It's not null.
There is no problem in a thread , So in multiple threads ,JVM The optimization of instruction rearrangement may lead to problems , Because the order of the second and third steps is not guaranteed , The final order of execution may be 1-2-3 It could be 1-3-2. If it's the latter , It's in 3 completion of enforcement 、2 Before execution , By thread two , At this time instance Right and wrong null 了 ( But it's not initialized ), So thread two will directly return instance, And then use , The pointer will be null . On a higher level , One thread is instance No more null But initialization is still not complete In the middle , At this time, there is a thread just ready to execute to the first if(instance==null), What we get here instance It's not null, And he used it directly , There will be errors . For this question , The solution we use is to add volatile keyword .
public class Singleton { private static volatile Singleton instance = null; private Singleton() {} public static Singleton getInstance() { if (instance == null){ synchronized(Singleton.class){ if (instance == null) instance = new Singleton(); } } return instance; } }
volatile The role of : Prohibit command rearrangement , hold instance Declare as volatile after , There will be a memory barrier to write to it , such , Before its assignment is complete , You don't have to call read operations . That is, it is not completely completed in a thread instance = new Singleton(); Before , Other threads cannot call read operations .
- The implementation of the above methods is based on the fact that there is no complex serialization and reflection , Otherwise, there may be problems , And the last way is to use enumeration to implement singletons , This is an ideal singleton pattern , It's also the most recommended way to write :
public enum Singleton { INSTANCE; public void doSomething() { } }
边栏推荐
- What is online account opening? Is it safe to open an account online now?
- At compilation environment setup -win
- 想请教一下,我在东莞,到哪里开户比较好?手机开户是安全么?
- I would like to ask what securities dealers recommend? Is it safe to open a mobile account?
- 现在券商的优惠开户政策什么?实际上网上开户安全么?
- Research Report on the overall scale, major manufacturers, major regions, products and application segmentation of multi-channel signal conditioners in the global market in 2022
- Cs5268 perfectly replaces ag9321mcq typec multi in one docking station solution
- sql-labs
- After eight years of test experience and interview with 28K company, hematemesis sorted out high-frequency interview questions and answers
- [译]深入了解现代web浏览器(一)
猜你喜欢
After 65 days of closure and control of the epidemic, my home office experience sharing | community essay solicitation
Redis sentinel cluster working principle and architecture deployment # yyds dry goods inventory #
HDL design peripheral tools to reduce errors and help you take off!
pytorch 模型保存的完整例子+pytorch 模型保存只保存可训练参数吗?是(+解决方案)
Jetson XAVIER NX上ResUnet-TensorRT8.2速度与显存记录表(后续不断补充)
Codeforces round 651 (Div. 2) (a thinking, B thinking, C game, D dichotomy, e thinking)
The first of the classic quotations of correspondents is heartbreaking
AcWing 340. Solution to communication line problem (binary + double ended queue BFS for the shortest circuit)
【QT】QPushButton创建
Taiwan SSS Xinchuang sss1700 replaces cmmedia cm6533 24bit 96KHz USB audio codec chip
随机推荐
Research Report on the overall scale, major manufacturers, major regions, products and applications of outdoor vacuum circuit breakers in the global market in 2022
I did a craniotomy experiment: talk about macromolecule coding theory and Lao Wang's fallacy from corpus callosum and frontal leukotomy
Sometimes only one line of statements are queried, and the execution is slow
Select function
1005 spell it right (20 points) "PTA class a exercise"
[Chongqing Guangdong education] reference materials for labor education of college students in Nanjing University
「 工业缺陷检测深度学习方法」最新2022研究综述
In the era of consumer Internet, a few head platforms have been born
【每日一题】241. 为运算表达式设计优先级
功能、作用、效能、功用、效用、功效
Resunnet - tensorrt8.2 Speed and Display record Sheet on Jetson Xavier NX (continuously supplemented)
Customized Huawei hg8546m restores Huawei's original interface
【Kubernetes系列】kubeadm reset初始化前后空间、内存使用情况对比
在网上炒股开户安全吗?我是新手,还请指导
[kubernetes series] comparison of space and memory usage before and after kubedm reset initialization
Cs5268 perfectly replaces ag9321mcq typec multi in one docking station solution
在券商账户上买基金安全吗?哪里可以买基金
SBT tutorial
[source code analysis] model parallel distributed training Megatron (5) -- pipestream flush
Wu Enda's machine learning mind mapping insists on clocking in for 23 days - building a knowledge context, reviewing, summarizing and replying