Context
Implementation Policy
Result Context
Context
You wantC #. You must have only one instance class and provide a global access point for accessing the instance. You want to ensure that your solution is efficient and can useMicrosoft? . NETCommon Language Runtime library function. You may also want to ensure that the solution is thread-safe.
Back to Top
Implementation Policy
AlthoughSingletonIs a relatively simple mode, but there are different factors and options related to the specific implementation. The following describes a set of implementation strategies and their advantages and disadvantages.
Singleton
SingletonThe following implementation of the Design Pattern usesDesign Patterns: Elements of Reusable Object-Oriented Software [Gamma95]The solution described in, but modified it to take advantageC #Available language functions, such as attributes:
using System; public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton Instance { get { if (instance == null) { instance = new Singleton(); } return instance; } } }
This implementation has two main advantages:
Because the instance is inInstanceThe property method is created internally, so the class can use additional features (for example, instantiate the subclass), even if it may introduce unwanted dependencies.
It is called "lazy instantiation" until the object requires an instance to be generated ". Lazy instantiation avoids unnecessary instantiation during application startupSingleton.
However, the main disadvantage of this implementation is that it is insecure in a multi-threaded environment. If different threads in the execution process enterInstanceAttribute method, you may create multipleSingletonObject instance. Each thread executes the following statements and determines that a new instance must be created:
if (instance == null)
There are many ways to solve this problem. One way is to useDouble-Check Locking [Lea99]. The C # and common language runtime libraries also provide a "static initialization" method, which can solve these problems without explicitly writing thread security code.
Static Initialization
One of the reasonsDesign Patterns [Gamma95]One of the reasons for avoiding static Initialization is,C ++The specification leaves some ambiguity in the initialization sequence of static variables. Fortunately,. NET FrameworkThe variable initialization method solves this ambiguity:
public sealed class Singleton { private static readonly Singleton instance = new Singleton(); private Singleton(){} public static Singleton Instance { get { return instance; } } }
In this policy, an instance is created when any member of the class is referenced for the first time. The Common Language Runtime Library processes variable initialization. This class is markedSealedTo prevent derivation, and the derivation may increase the number of instances. ForSealedFor more information, see[Sells03]. In addition, the variable is markedReadonlyThis means that only variables can be allocated during static initialization (the example shown here) or in the class constructor.
This implementation is similar to the previous example. The difference is that it depends on the Common Language Runtime Library to initialize variables. It can still be used to solveSingletonThe two basic problems that pattern tries to solve: Global Access and instantiation control. The public static attribute provides a global access point for the access instance. In addition, because constructors are private, they cannot be instantiated outside the class itself.SingletonTherefore, a variable references a unique instance that can exist in the system.
BecauseSingletonThe instance is referenced by a private static member variable.InstanceThe property is not instantiated until it is referenced by the call. ThereforeDesign PatternsFormatSingletonSimilarly, this solution implements a form of lazy instantiation attribute.
The only potential disadvantage of this method is that you have less control over the instantiation mechanism. InDesign PatternsForm, you can use non-default constructor or execute other tasks before instantiation. In this solution. NET FrameworkPerform initialization, so you do not have these options. In most cases, static Initialization is performed in. NETImplementationSingleton.
Multithreading Singleton
Static Initialization is suitable for most cases. If your application must delay instantiation, use non-Default constructors before instantiation, or execute other tasks, and work in a multi-threaded environment, you need another solution. However, in some cases, you cannot rely on the Common Language Runtime Library as in the "static initialization" example to ensure thread security. In this case, you must use a specific language function to ensure that only one object instance is created in the case of multithreading. One of the more common solutions is to useDouble-Check Locking [Lea99]Technology to prevent different threads from being created at the same timeSingleton.
Note:The Common Language Runtime Library solves the problems that are common in other environments.Double-Check LockingRelated Questions. For more information about these issues, see"The 'double-Checked Locking Is broken' Declaration", URL for http://www.cs.umd.edu /~ API/java/memoryModel/DoubleCheckedLocking.html.
The following implementation only allows a thread to be created before it is createdSingletonWhen the instance is in the key area (this area is composedLockBlock ID ).
using System; public sealed class Singleton { private static volatile Singleton instance; private static object syncRoot = new Object(); private Singleton() {} public static Singleton Instance { get { if (instance == null) { lock (syncRoot) { if (instance == null) instance = new Singleton(); } } return instance; } } }
This method ensures that only one instance is created when an instance is required. In addition, the variable is declaredVolatileTo ensure that the instance variables can be accessed only after the instance variables are allocated. Finally, this method is usedSyncRootTo avoid deadlocks.
ThisDouble-check lockingThe method solves the thread concurrency problem and avoidsInstanceAn exclusive lock exists in all calls to the property method. It also allows you to delay Instantiation to the first time an object is accessed. In fact, applications seldom need this type of implementation. In most cases, the static initialization method is sufficient.
Back to Top
Result Context
InC #ImplementationSingletonIt has the following advantages and disadvantages:
Advantages
Because. NET FrameworkThe static initialization method is possible because it explicitly specifies how and when static variable initialization occurs.
Multi-thread before a columnSingleton"As described inDouble-Check LockingThe technology has been correctly implemented in the public Language Runtime Library.
Disadvantages
If your multi-threaded application requires Explicit initialization, you must take measures to avoid thread problems.
Http://msdn.microsoft.com/zh-cn/library/ms998558.aspx
VolatileKeyword indicates that the field may be modified by multiple concurrent execution threads. DeclaredVolatileFields are not restricted by the compiler optimization (assuming that they are accessed by a single thread. This ensures that the field displays the latest value at any time.