剑指offer面试题2 Singleton 模式 三种方法,设计多线程 同步锁

来源:互联网 发布:md5加密算法 java 编辑:程序博客网 时间:2024/05/16 15:59
Singleton是一种非常经典的设计模式 这种类 只能有一个实例
常用的设计模式中 Singleton是唯一能用短短几十行代码写完的 所以常做面试题


三种解法
不好的解法1 只使用单线程的环境
public sealed class Singleton1
{
private Singleton1()
{}
private static Singleton1 instance=nulll;
public static Singleton1 Instance
{
get{
if(instance == null)
instance=new Singleton1();
return instance;
}
}
}
如果有两个线程同时运行到判断 instance是否是null 并且此时没有创建
那么两个线程都会创建一个实例


第二种解法 加同步锁
public sealed class Singleton2
{
private Singleton2{}


private static readonly object syncObj = new object();
private static Singleton2 instance = null;
public static Singleton2 Instance
{
get
{
lock(syncObj)
{
if(instance==null)
instance = new Singleton2();
}
return instance;
}
}
}


虽然多线程 但是效率不高。 因为加锁非常耗时间


解法三


修改解法二 只在实例没有创建的时候加锁
也就是两次判断 实例是不是已经创建了
就是在上面代码 lock 外面再加一层 if(instance == null)
可以提高效率


强烈推荐的解法四
C#中有一个函数,只执行一次 就是静态构造函数


public sealed class Singleton4
{
private Singleton4(){}
private Singleton4 instance = new Singleton4();
public static Singleton4 Instance
{
get{ return instance;}
}

}
这样还有问题 就是 实例创建早了 占用内存


强烈推荐的解法五 按需创建
public sealed class Singleton5
{
Singleton5(){}
public static Singleton5 Instance
{
get{ return Nested.instance;}
}


class Nested
{
static Nested(){}
internal static readonly Singleton5 instance = new Singleton5();
}
}


内部定义了私有类型 Nested 只在属性Instance中被用到 所以 第一次试图通过属性Instance得到 实例时 会自动调用Nested的 静态构造函数 做到了按需调用。