您的位置 首页 杂谈

C# 单例模式

公司职员 电影,撼动世界的调律师,rockbros

一、多线程不安全方式实现 ?12345678910111213141516public sealed class SingleInstance{private static Sin…

一、多线程不安全方式实现

?12345678910111213141516public sealed class SingleInstance{private static SingleInstance instance;private SingleInstance() { }public static SingleInstance Instance{get{if (null == instance){instance = new SingleInstance();}return instance;}}}

  sealed表示SingleInstance不能被继承。其实构造函数私有化已经达到了这个效果,私有的构造函数不能被继承。为了可读性,可以加个sealed。

不安全的单例指的是在多线程环境下可能有多个线程同时进入if语句,创建了多次单例对象。

二、安全的单例模式

?123456789101112131415161718192021222324public sealed class SingleInstance{private static volatile SingleInstance instance;private static readonly object obj = new object();private SingleInstance() { }public static SingleInstance Instance{get{if (null == instance){lock (obj){if (null == instance){instance = new SingleInstance();}}}return instance;}}}

 加锁保护,在多线程下可以确保实例值被创建一次。缺点是每次获取单例,都要进行判断,涉及到的锁和解锁比较耗资源。

三、只读属性式

?123456789101112public sealed class SingleInstance{private static readonly SingleInstance instance = new SingleInstance();private SingleInstance() { }public static SingleInstance Instance{get{return instance;}}}

   借助readonly属性,instance只被初始化一次,同样达到了单例的效果。在Main函数执行第一句话之前,instance其实已经被赋值了,并不是预期的 只有到访问Instance变量时才创建对象。

如下代码:

?123456789101112131415161718192021class Program{static void Main(string args){Console.WriteLine("Begin");var temp = SingleInstance.instance; ;}}public sealed class SingleInstance{public static readonly SingleInstance instance = new SingleInstance();private SingleInstance(){Console.WriteLine("初始化初始化!");}public static SingleInstance Instance{get { return instance; }}}

  输出:

在执行第一句代码之前,实例已经被初始化。

解决方法是在SingleInstance中加上静态构造函数。

?12345678910111213public sealed class SingleInstance{public static readonly SingleInstance instance = new SingleInstance();static SingleInstance() { }private SingleInstance(){Console.WriteLine("初始化初始化!");}public static SingleInstance Instance{get { return instance; }}}

  在运行输出:

四、使用Lazy

?123456789101112public sealed class SingleInstance{private static readonly LazySingleInstance instance = new LazySingleInstance(() = new SingleInstance());private SingleInstance(){}public static SingleInstance Instance{get{return instance.Value;}}}

  Lazy默认是线程安全的。MSDN描述如下:

Will the lazily initialized object be accessed from more than one thread?Lazylt;Tgt; 对象可以创建在所有线程。”>If so, theLazyTobject might create it on any thread.Lazylt;Tgt; 对象的一个简单的构造函数,因此,仅延迟实例化的对象创建实例,就多个线程尝试访问它。”>You can use one of the simple constructors whose default behavior is to create a thread-safeLazyTobject, so that only one instance of the lazily instantiated object is created no matter how many threads try to access it.Lazylt;Tgt; 对象,则必须使用不允许您指定线程安全性的构造函数。”>To create aLazyTobject that is not thread safe, you must use a constructor that enables you to specify no thread safety.

Lazylt;Tgt; 对象可以创建在所有线程。”>Lazylt;Tgt; 对象的一个简单的构造函数,因此,仅延迟实例化的对象创建实例,就多个线程尝试访问它。”>Lazylt;Tgt; 对象,则必须使用不允许您指定线程安全性的构造函数。”>

五、泛型单例

?123456789101112131415161718192021222324252627282930313233class Program{static void Main(string args){Console.WriteLine("Begin");mySingle.Instance.age = 500;Console.WriteLine(mySingle.Instance.age);}}public abstract class SingleInstanceT{private static readonly LazyT _instance = new LazyT(() ={var ctors = typeof(T).GetConstructors(BindingFlags.Instance| BindingFlags.NonPublic| BindingFlags.Public);if (ctors.Count() != 1)throw new InvalidOperationException(String.Format("Type {0} must have exactly one constructor.", typeof(T)));var ctor = ctors.SingleOrDefault(c = c.GetParameters().Count() == 0 c.IsPrivate);if (ctor == null)throw new InvalidOperationException(String.Format("The constructor for {0} must be private and take no parameters.", typeof(T)));return (T)ctor.Invoke(null);});public static T Instance{get{ return _instance.Value;}}}public class mySingle : SingleInstancemySingle{private mySingle() { }public int age;}

  

本文来自网络,不代表加推新闻网立场,转载请注明出处:http://www.bafangmiaomu.com/shehui/98143/

作者: 头条新闻

为您推荐