单例模式
饿汉式
懒汉式
懒汉双加锁
静态内部类
C#特有写法
破坏单例
- 定义:有且仅有一个实例,节省资源。
- 构造函数私有化
- 静态只读私有字段
- 静态公开的获取私有字段的方法
饿汉式
public class HungryMan
{
// 构造函数私有化
private HungryMan() { }
// 静态只读私有字段
private readonly static HungryMan _HungryMan = new HungryMan();
// 静态获取私有字段的方法,也可以写个属性
public static HungryMan GetHungryMan()
{
return _HungryMan;
}
}
问题:
- 由于有静态字段,所以程序加载静态字段就加载,即使目前用不到,他也会加载,所以有一定的资源浪费。
懒汉式
public class LazyMan
{
private LazyMan() { }// 构造函数私有化
private static LazyMan _LazyMan;// 私有字段
public static LazyMan GetLazzyMan() // 静态获取私有字段的方法
{
if (_LazyMan==null)
{
_LazyMan = new LazyMan();
}
return _LazyMan;
}
}
问题
- 线程不安全,可能同时有多个线程同时进入if中
改造
- 加一个互斥锁
public class LazyMan
{
private LazyMan() { }// 构造函数私有化
private static LazyMan _LazyMan;// 私有字段
private static object o = new object();
public static LazyMan GetLazzyMan() // 静态获取私有字段的方法
{
lock (o)// 互斥锁,只允许一个线程进入。其实就是Monitor.Enter() Monitor.Exit()
{
if (_LazyMan == null)
{
_LazyMan = new LazyMan();
}
}
return _LazyMan;
}
}
问题
- 每次都进互斥锁,有额外性能开销
_LazyMan = new LazyMan();
的正常顺序为:- 1.开辟内存空间
- 2.创建一个对象
- 3.对象指向内存空间
- 可能会有极端情况使123乱序为132,即指针重排,所以字段加
volatile
关键字
改造:饿汉双加锁
public class LazyMan
{
private LazyMan() { }// 构造函数私有化
private volatile static LazyMan _LazyMan;// 私有字段,加volatile
private static object o = new object();
public static LazyMan GetLazzyMan() // 静态获取私有字段的方法
{
if (_LazyMan == null)
{
lock (o)// 互斥锁,只允许一个线程进入。其实就是Monitor.Enter()Monitor.Exit()
{
if (_LazyMan == null)
{
_LazyMan = new LazyMan();
}
}
}
return _LazyMan;
}
}
静态内部类改造饿汉式
public class HungryStaticMan
{
private HungryStaticMan() {}
// 静态内部类
public static class InnerClass
{
public static HungryStaticMan _HungryStaticMan=new HungryStaticMan();
}
// 静态获取方法
public static HungryStaticMan GetStaticMan()
{
return InnerClass._HungryStaticMan;
}
}
优点
* 用的时候创建,不会浪费空间
C#提供的懒汉式
public class SampleLazyMan
{
private SampleLazyMan() {}
private static readonly Lazy<SampleLazyMan> Lazy=new Lazy<SampleLazyMan>(()=>new SampleLazyMan());
public SampleLazyMan GetLazyMan()
{
return Lazy.Value;
}
}
优点
- 线程安全
破坏单例
用反射,获取单例的构造函数。可以在单例的构造函数中加标志位避免,但标志位同样可以在单例中获取,所以“防君子不防小人”。
标签:静态,模式,LazyMan,static,private,单例,new,设计模式,public From: https://www.cnblogs.com/Hanwen680/p/17566565.html