c# 多线程单例模式_C# 设计模式之单例模式

原标题:C# 设计模式之单例模式

单例模式:一个类在内存中只有一个对象(实例),并且提供一个可以全局访问或者获取这个对象的方法。

这两天学的,写了个小例子,问了同事一些关于线程的问题,还有从网上查了一些资料。还犯了一些低级的错误。

vs2017控制台输出文字乱码,从网上找了一些方法不管用,最后发现是自己新建项目选错模板了,选择了.NET CORE的模板,所以才会输出乱码,大家一定要吸取教训。

直接上代码

演示类,Person.cs

public class Person

{ ///

/// 实例化一个私有静态变量,存储类本身的实例

///

private static Person _person = null;

///

/// 构造函数

///

private Person()

{

Console.WriteLine("构造了一个{0}",GetType().Name);

}

public static Person GetInstance()

{ if(_person == null)

_person = new Person(); return _person;

}

}

客户端代码:

{

varperson1 =Person.GetInstance();

varperson2 =Person.GetInstance();

varperson3 =Person.GetInstance();

Console.WriteLine("person1 == person2:{0}", object.ReferenceEquals(person1, person2));}

输出结果:

只输出了一次,两个对象引用相等。说明单例模式没问题。

进阶:

public class Person

{ ///

/// 实例化一个私有静态变量,存储类本身的实例

///

private static Person _person = null;

///

/// 构造函数

///

private Person()

{

Console.WriteLine("构造了一个{0}",GetType().Name);

} public static Person GetInstance()

{ if (_person == null)

_person = new Person(); return _person;

}

}

客户端调用代码:

{

Person person1 = null;

Person person2 = null;

Person person3 = null;

//多线程下可以输出多次

var thread1 = new Thread(() => { person1 = Person.GetInstance(); });

var thread2 = new Thread(() => { person2 = Person.GetInstance(); });

var thread3 = new Thread(() => { person3 = Person.GetInstance(); });

thread1.Start();

thread2.Start();

thread3.Start();

Thread.Sleep(1000);//等待子线程完成

Console.WriteLine("person1 == person2:{0}", object.ReferenceEquals(person1, person2));

}

输出结果:

输出了多次,引用也不相等。说明多次实例化这个类,单例模式写的不完全正确,那让我们加上线程安全验证。

继续进阶:

public class Person

{ ///

/// 实例化一个私有静态变量,存储类本身的实例

///

private static Person _person = null;

///

/// 作为锁的对象,使用私有的、静态的并且是只读的对象

///

private static readonly object _obj = new object();

///

/// 构造函数

///

private Person()

{

Console.WriteLine("构造了一个{0}",GetType().Name);

}

///

/// 获取类唯一的实例对象

///

public static Person GetInstance()

{

if (_person == null)//先判断是否为空

{ l

ock (_obj)//再判断下是否有别的线程在使用

{

if (_person == null)

//等其他线程使用完成后再判断是否为空

{

_person = new Person();

}

}

} return _person;

}

}

客户端调用代码:

{

//使用锁,锁住的对象:使用私有的、静态的并且是只读的对象

Person person1 = null;

Person person2 = null;

Person person3 = null;

//多线程下可以输出多次

var thread1 = new Thread(() => { person1 = Person.GetInstance(); });

var thread2 = new Thread(() => { person2 = Person.GetInstance(); });

var thread3 = new Thread(() => { person3 = Person.GetInstance(); });

thread1.Start();

thread2.Start();

thread3.Start();

Thread.Sleep(1000);//等待子线程完成

Console.WriteLine("person1 == person2:{0}", object.ReferenceEquals(person1, person2));

}

输出结果:

输出一次,引用相等,说明单例模式成功,线程安全已经加上。

进阶2

可以使用静态构造函数作为单例模式:

public class Person

{ ///

/// 实例化一个私有静态变量,存储类本身的实例

///

private static Person _person = null;

///

/// 构造函数

///

private Person()

{

Console.WriteLine("构造了一个{0}",GetType().Name);

}

///

/// 静态构造函数,只执行一次

///

static Person()

{

_person = new Person();

}

///

/// 获取类的实例

///

public static Person GetInstance()

{ return _person;

}

}

客户端代码:

{

//使用锁,锁住的对象:使用私有的、静态的并且是只读的对象

//使用静态构造函数,在里面初始化person对象

Person person1 = null;

Person person2 = null;

Person person3 = null;

//多线程下可以输出多次

var thread1 = new Thread(() => { person1 = Person.GetInstance(); });

var thread2 = new Thread(() => { person2 = Person.GetInstance(); });

var thread3 = new Thread(() => { person3 = Person.GetInstance(); });

thread1.Start();

thread2.Start();

thread3.Start();

Thread.Sleep(1000);//等待子线程完成

Console.WriteLine("person1 == person2:{0}", object.ReferenceEquals(person1, person2));

}

输出一次,引用相等,静态构造函数也可以作为单例模式实现的一种方法。返回搜狐,查看更多

责任编辑:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值