Implementation of the C # Singleton pattern and examples of performance comparisons

Source: Internet
Author: User
This article mainly introduces the implementation of the C # Singleton model and performance comparison of the relevant data, detailed introduction of 6 ways to achieve, the need for friends can refer to the next

Brief introduction

A singleton refers to a class that can only have one instance (in C #, it is more accurate to say that only one instance of the class exists in each AppDomain, which is one of the most used patterns in software engineering. After the first user has created an instance of this class, it is necessary to use this class to use the previously created instance, and no more new instances can be created. Typically, a single meeting is created the first time it is used. This article describes how several singleton implementations in C # are implemented, and analyzes the thread safety and performance differences between them.

There are many ways to implement a singleton, but from the simplest implementations (non-lazy loading, non-thread-safe, inefficient) to lazy loading, thread-safe, and efficient implementations, they all have some basic similarities:

    • The Singleton class has only one private parameterless constructor

    • Class declared as sealed (not required)

    • A static variable in the class holds a reference to the instance that is created

    • The Singleton class provides a static method or property to return a reference to the created instance (eg. getinstance)

Several implementations

One non-thread safe

Bad code! Do not use!public sealed class singleton{  private static Singleton instance = null;  Private Singleton ()  {  } public  static Singleton instance  {    get    {      if (instance = = null)      {        instance = new Singleton ();      }      return instance;}}  }

This method is not thread-safe, there will be two threads executing if (instance = = null) and two different instance are created, and the created will replace the newly created one, causing the reference to be empty.

Two simple thread-safe implementations

public sealed class singleton{  private static Singleton instance = null;  private static ReadOnly Object padlock = new Object ();  Singleton ()  {  } public  static Singleton Instance  {    get    {      lock (padlock)      {        if (instance = = null)        {          instance = new Singleton ();        }        return instance;}}}  

Compared to implementation one, this version adds a lock to the instance, locks the padlock before calling instance, thus avoiding thread conflicts in the implementation, which creates only one instance from start to finish. However, because the lock is used every time the call to instance, and the cost of the call lock is large, this implementation will have some performance penalty.

Note Here we are using a new private object instance padlock to implement the lock operation, rather than locking the singleton directly. There is a potential risk of locking the type directly, because this type is public, so in theory it will be called in any code, and locking it directly can cause performance problems and even deadlock situations.

In note:c#, the same thread can be locked multiple times for an object, but if the threads are locked at the same time, there may be thread waits or a serious deadlock condition. Therefore, when we use lock, we try to lock the private variables in the class so that we can avoid this situation.

Thread-safe implementation of three-factor authentication

public sealed CALSS singleton{  private static Singleton instance = null;  private static ReadOnly Object padlock = new Object ();  Singleton ()  {  } public  static Singleton Instance  {    get    {      if (Instance = = null)      {        Lock (padlock)        {          if (instance = = null)          {            instance = new Singleton ()          ;      }}} return instance;    }  } }

While ensuring thread safety, this implementation also avoids the lock operation for every call to instance, which can save a certain amount of time.

However, this implementation has its drawbacks as well:

1 cannot work in Java. (For specific reasons can be seen in the original, this side does not understand how)

2 programmers are prone to error when they implement them. If you make your own changes to the code of this pattern, be more careful because the logic of double check is more complex and prone to poor thinking and error.

Four thread-safe implementations without locks

public sealed class singleton{  //The initialization of instance is performed when Singleton is first invoked  private static readonly Singleton = New Singleton ();  Explicit static consturctor to tell C # compiler   //not to mark type as beforefieldinit  static Singleton ()  {
  }  Private Singleton ()  {  } public  static Singleton Instance  {    get    {      return instance;}}}  

This implementation is simple and does not use locks, but it is still thread-safe. A static,readonly singleton instance is used here, which creates a new instance when the singleton is first called, and the thread safety guarantee is created here. NET direct control, we can think of it as an atomic operation, and it will only be created once in a appdomaing.

This implementation also has some drawbacks:

1instance was created in an unknown time, any call to Singleton will be created in advance instance
Cyclic invocation of the 2static constructor. In the case of A, B, and two classes, A's static constructor invokes a, and a is called in the static constructor of B, both of which form a cyclic call that seriously causes the program to crash.
3 We need to manually add singleton static constructors to ensure that the singleton type is not automatically added beforefieldinit this attribute to ensure that instance is created the first time Singleton is called.
The 4readonly property cannot be changed at runtime, and if we need to dispose of the instance and recreate a new instance while the program is running, this implementation cannot be satisfied.

Five full delay load implementations (fully lazy instantiation)

public sealed class singleton{  private Singleton ()  {  } public  static Singleton Instance   {    get    {      return nested.instance;    }  }  Private class Nested  {    //Explicit static constructor to tell C # compiler    //not to mark type as Beforefiel Dinit    Static Nested ()    {    }    internal static readonly Singleton instance = new Singleton ();}  }

Implementation of the five is to achieve four of the packaging. It ensures that the instance is only called in the instance get method and is initialized only before the first call. It is a version that implements four to ensure lazy loading.

Six uses. NET4 type of lazy<t>

public sealed class singleton{  private static readonly lazy<singleton> Lazy = new Lazy<singleton> (() => ; New Singleton ());  public static Singleton Instance   {    get     {      return lazy. Value;    }  }  Private Singleton ()  {  }}

. NET4 or later supports lazy<t> for lazy loading, which guarantees a single case of thread-safe and lazy-load features with the most concise code.

Performance differences

In previous implementations, we were emphasizing thread safety and lazy loading of code. In practice, however, if the initialization of your singleton class is not a time-consuming operation or the initialization sequence does not cause a bug, deferred initialization is an optional feature because the time taken to initialize is negligible.

In a real-world scenario, if your singleton instance is frequently called (in a loop, for example), the performance cost to ensure thread safety is a more interesting place.

In order to compare the performance of these implementations, I made a small test that loops through the implementation of the singleton 900 million times, each call instance method to perform a count++ operation, every 1 million output once, the running environment is the MBP on the visual Studio for Mac. The results are as follows:


Thread Safety Lazy Loading Test Run time (ms)
Achieve a Whether Is 15532
Implementation two Is Is 45803
Implementation three Is Is 15953
Implementation Four Is Not exactly 14572
Implementation Five Is Is 14295
Implementation Six Is Is 22875

The test method is not rigorous, but it can still be seen that method two is the most time-consuming, almost three times times more than the other, because each call to lock. The second is the implementation of the. NET lazy type, which is about One-second more than the others. The remaining four, there is no obvious difference.

Summarize

In general, many of the above-mentioned single implementations are not very wide in today's computer performance, unless you need a particularly large concurrent amount of call instance, you will need to consider the performance of the lock.

For the general developer, the use of method two or method Saturday implementation of the Singleton is good enough, the method four and five need to have a good understanding of C # running process, and the implementation of the need to master a certain skill, and they save time is still limited.

Reference

Most of this article is translated from implementing the Singleton Pattern in C #, plus part of your own understanding. This is what i saw when I searched for static readonly field initializer vs static constructor initialization, where I thanked two authors.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.