设计模式-(2)单例模式(Singleton Pattern)

单例模式(Singleton Pattern)

定义:Ensure a class has only one instance, and provide a global point of access to it.(确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。)

使用场景:
1)要求生成唯一序列号的环境;
2)在整个项目中需要一个共享访问点或共享数据,例如一个Web页面上的计数器,可以不用把每次刷新都记录到数据库中,使用单例模式保持计数器的值,并确保是线程安全的;
3)创建一个对象需要消耗的资源过多,如要访问IO和数据库等资源;
4)需要定义大量的静态常量和静态方法(如工具类)的环境,可以采用单例模式(当然,也可以直接声明为static的方式)。

通用代码:(是线程安全的)

 public class Singleton
 {
    /// <summary>
    ///  自己主动创建实例
    /// </summary>
    private static readonly Singleton instance = new Singleton();

    /// <summary>
    /// 私有构造函数,限制产生多个对象
    /// </summary>
    private Singleton()
    {
    }

    /// <summary>
    /// 通过该方法获得实例对象
    /// </summary>
    /// <returns></returns>
    public static Singleton GetInstance()
    {
        return instance;
    }

    /// <summary>
    /// 类中其他方法,尽量是static
    /// </summary>
    public static void DoSomething()
    {
    }
}

线程不安全实例:

public class Singleton2
{
    private static Singleton2 instance = null;

    /// <summary>
    /// 私有构造函数,限制产生多个对象
    /// </summary>
    private Singleton2()
    {
    }

    /// <summary>
    /// 通过该方法获得实例对象
    /// </summary>
    /// <returns></returns>
    public static Singleton2 GetInstance()
    {
        if (instance == null)
        {
            instance = new Singleton2();
        }

        return instance;
    }


    /// <summary>
    /// 类中其他方法,尽量是static
    /// </summary>
    public static void DoSomething()
    {
    }

}

上面的单例模式的实现在单线程下确实是完美的,然而在多线程的情况下会得到多个Singleton实例,因为在两个线程同时运行GetInstance方法时,此时两个线程判断(instance ==null)这个条件时都返回真,此时两个线程就都会创建Singleton的实例,这样就违背了我们单例模式初衷了,既然上面的实现会运行多个线程执行,那我们对于多线程的解决方案自然就是使GetInstance方法在同一时间只运行一个线程运行就好了,也就是我们线程同步的问题了

解决办法:
在 instance 变量前 添加 volatile 关键字,再添加一个同步锁对象,保证线程安全。

public class Singleton3
{
    /// <summary>
    ///  volatile 关键字指示一个字段可以由多个同时执行的线程修改。
    ///  声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制。
    ///  这样可以确保该字段在任何时间呈现的都是最新的值。
    ///  volatile 修饰符通常用于由多个线程访问但不使用 lock 语句对访问进行序列化的字段。
    /// </summary>
    private volatile static Singleton3 instance = null;
    /// <summary>
    ///  同步锁对象
    /// </summary>
    private static readonly object _lockSyncObject = new object();

    /// <summary>
    /// 私有构造函数,限制产生多个对象
    /// </summary>
    private Singleton3()
    {
    }

    /// <summary>
    /// 通过该方法获得实例对象
    /// </summary>
    /// <returns></returns>
    public static Singleton3 GetInstance()
    {
        if (instance == null)
        {
            lock (_lockSyncObject)
            {
                instance = new Singleton3();
            }
        }

        return instance;
    }


    /// <summary>
    /// 类中其他方法,尽量是static
    /// </summary>
    public static void DoSomething()
    {
    }

}

猜你喜欢

转载自blog.csdn.net/num197/article/details/80286746