标签:运行 设计 returns 一个 解锁 竞争 turn summary ret
一、单例模式定义:
确保一个类只有一个实例,并提供一个访问它的全局访问点。
二、背景:
当我们的系统中某个对象只需要一个实例的情况,例如:操作系统中只能有一个任务管理器,操作文件时,同一时间内只允许一个实例对其操作等。
三、实现思维:
1、私有化构造函数,使外界不能创建该类实例。
2、声明一个静态变量接收类的实例。
3、定义一个静态共有方法提供全局访问。
四、相关代码:
1、简单例子:
众所周知,我们添加一个按钮事件show出另外一个窗体,一般的做法是new一个窗体对象然后去show,但是每点击一次都会show多出一个新窗体。那怎么样才能做到点击一个show出一个窗体之后只要新窗体不关闭,不管我们再怎么点击也不会show多新窗体呢?这里就是用到单例模式了,相关代码如下:
public partial class Form2 : Form { //定义一个静态变量来保存类的实例 public static Form2 FrmSingle = null; //私有化构造函数,使外界不能创建该类实例 private Form2() { InitializeComponent(); } /// <summary> /// 定义静态公有方法提供全局访问 /// </summary> /// <returns></returns> public static Form2 GetSingle() { // 如果类的实例不存在则创建,否则直接返回 if (FrmSingle == null) { FrmSingle = new Form2(); } return FrmSingle; } }
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { //调用窗体2静态方法实现单例模式 Form2 frm = Form2.GetSingle(); frm.Show(); } }
通过上面的简单例子,相信大家也觉得单例模式并不难,但是上面的单例模式的实现是单线程的,然而在多线程的情况下会得到多个Form2实例,因为在两个线程同时运行GetSingle方法时,此时两个线程判断(FrmSingle ==null)这个条件时都返回真,此时两个线程就都会创建Form2的实例,这样就违背了我们单例模式初衷了,解决方法也很简单,使GetSingle方法在同一时间只运行一个线程运行就好了。
//定义一个静态变量来保存类的实例 public static Form2 FrmSingle = null; //定义一个标识确保线程同步 public static readonly object locker = new object(); //私有化构造函数,使外界不能创建该类实例 private Form2() { InitializeComponent(); } /// <summary> /// 定义公有方法提供全局访问 /// </summary> /// <returns></returns> public static Form2 GetSingle() { if (FrmSingle == null) { lock (locker) { // 如果类的实例不存在则创建,否则直接返回 if (FrmSingle == null) { FrmSingle = new Form2(); } } } return FrmSingle; } }
有些小伙伴或许会好奇,为什么还要多加一次if条件判定,是因为多线程存在竞争的资源的问题,如果两个线程同时运行lock外层的if (FrmSingle == null),都成立,第一条线程加锁实例化一个对象,解锁后,如果不加判断,第二条线程直接实例化一个对象,这就不是单例了。这样也可以减少多线程情况下每次都需要获取线程锁的资源,如果对象已经被实例化了就可以不用加锁了,节省了系统资源。
五、总结
单例模式,这个知识点并不难,在学校也学习过,但是一些加深的应用例如上面的多线程的情况也是通过博友们的分享才知道会有这个问题,并且知道怎么去解决。所谓从浅入深,了解清楚并巩固加深最基本的设计模式方便日后我们继续学习剩下的设计模式!
标签:运行 设计 returns 一个 解锁 竞争 turn summary ret
原文地址:https://www.cnblogs.com/jiechou/p/9052615.html