目录
Double-Checked locking(DCL,双重检验锁)
单例模式
引言
对于系统中的某些类来说,只有一个实例很重要,例如在Windows系统中就只能打开一个任务管理器;一个党只能有一个主席;天上的太阳只有一个等。如何保证一个类只有一个实例且这个实例易于被访问呢?这就是单例模式要解决的问题。
单例模式重要等级★★★★☆ 单例模式难度等级★☆☆☆☆
定义
英文定义:"Ensure a class has only one instance and provide a global point of access to it"
单例模式某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称之为单例类,它提供全局的访问方法。
单例模式结构图
代码实现
根据单例模式结构图,以C#代码实现单例模式。步骤如下:
第一步,创建一个名为SingleDemo的类,将类的构造函数私有化;
第二步,在该类中声明一个静态的字段,字段类型就是该类的类型;
第三步,提供一个全局访问点(小技巧:visiual studio右击字段,可以自动生成代码,类似eclipse自动生成get,set方法,如图所示)。
具体代码如下:
public class SingleDemo
{
//私有化构造函数
private SingleDemo() { }
//唯一实例
private static SingleDemo instance;
//提供的全局访问点
public static SingleDemo Instance
{
get
{
if (instance == null)
instance = new SingleDemo();
return instance;
}
set => instance = value;
}
}
测试代码:
class Program
{
static void Main(string[] args)
{
SingleDemo singleA = SingleDemo.Instance;
SingleDemo singleB = SingleDemo.Instance;
Console.WriteLine("singleA: " + singleA.GetHashCode());
Console.WriteLine("singleB: " + singleB.GetHashCode());
Console.ReadKey();
}
}
运行结果:
测试代码将两个实例的hashcode打印出来,以此判定俩个实例是否是同一个实例。从打印结果来看,SingleA和SingleB是同一实例,实现了单例效果。
单例模式的进阶学习
上面代码中的单例模式的实现方式是最基本的实现方式,这种方式Lazy Loading(延迟加载)很明显,但是这种方式有个最大的缺点就是不支持多线程。接下介绍几种支持多线程的单例模式的代码实现。
饿汉式
只需要将第二行代码的private static SingleDemo instance;改为private static SingleDemo instance = new SingleDemo();即可利用类的加载机制(C#:CLR类加载器,JAVA:ClassLoder)避免多线程同步问题。这种实现方式instance在类装载的时候就实例化了,显然没有达到lazy loading的效果。但是这种实现方式非常简单,如果实例化instance不太消耗资源,那么饿汉式单例模式是种不错的选择。具体代码如下:
public class SingleDemo
{
//私有化构造函数
private SingleDemo() { }
//唯一实例
private static SingleDemo instance = new SingleDemo();
//提供的全局访问点
public static SingleDemo Instance { get => instance; set => instance = value; }
}
懒汉式
多线程同步问题最直接能想到的就是加同步锁,然而在单例模式中,同步锁只有首次实例化的时候起到作用,频繁的加锁势必会影响性能。相对饿汉式,懒汉式具备很好的lazy loading,避免了内存浪费。在instance实例化消耗资源较大的情况下,也是有可取之处。具体代码如下:
public class SingleDemo
{
//私有化构造函数
private SingleDemo() { }
//唯一实例
private static SingleDemo instance;
private static readonly object locker =