双检索------------------------------C#
1.双检索,用于类的访问,理论上可以提高效率。。。但是它在大多是时候是损害效率的。所以,在下面的一些代码里,记录了比双检索效率更高的方法
public sealed class Singleton { //这是为了线程安全才这样写的。。。。这样做的代价,比在构造函数中实例化要大 private static Object s_lock = new object(); //这个对象引用一个单实例对象 private static Singleton s_value = null; //私有化,防止外部实例化 private Singleton() { } public static Singleton GetSingleton() { //如果对象已经创建,就直接返回(这样速度很快) if (s_value != null) return s_value; Monitor.Enter(s_lock); //如果还没有创建,就创建它 if (s_value == null) { Singleton temp = new Singleton(); //将引用保存到s_value中 Volatile.Write(ref s_value, temp); } Monitor.Exit(s_lock); //返回引用 return s_value; } }
2.双检索的升级版
public sealed class Singleton { //这个对象引用一个单实例对象 private static Singleton s_value = null; //私有化,防止外部实例化 private Singleton() { } public static Singleton GetSingleton() { //如果对象已经创建,就直接返回(这样速度很快) if (s_value != null) return s_value; //创建一个实例对象,并把它固定下来 Singleton temp = new Singleton(); Interlocked.CompareExchange(ref s_value,temp,null); //这个技术的缺点是,,在多个线程同时访问这个方法时,会实例化多个对象。。。 //但是,这种情况几乎不会发生。。。。 //就算发生, 多创建的实例,之后也会被释放掉 return s_value; } }
3。我整理了一个方法,让这个技术更通用一点
public sealed class DoubleSearch<T> where T : class, new() { //这个对象引用一个单实例对象 private static T s_value=null ; //私有化,防止外部实例化 private DoubleSearch() { 构造函数里,千万不能有副作用的代码,也不希望能被外部类调用。。。所以声明为private,并且什么也不写 } public static T GetSingleton() { //如果对象已经创建,就直接返回(这样速度很快) if (s_value != null) return s_value; //创建一个实例对象,并把它固定下来 T temp = new T(); Interlocked.CompareExchange(ref s_value,temp,null); //这个技术的缺点是,,在多个线程同时访问这个方法时,会实例化多个对象。。。 //但是,这种情况几乎不会发生。。。。 //就算发生, 多创建的实例,之后也会被释放掉 return s_value; } }
4.c#的Lazy类其实已经封装了这链中代码。。。。。但是。既然已经写出来了,就不用C#自带的了