首页 > 代码库 > 单例模式在多线程环境下的lazy模式为什么要加两个if(instance==null)
单例模式在多线程环境下的lazy模式为什么要加两个if(instance==null)
刚才在看阿寻的博客”C#设计模式学习笔记-单例模式“时,发现了评论里有几个人在问单例模式在多线程环境下为什么lazy模式要加两个if进行判断,评论中的一个哥们剑过不留痕,给他们写了一个demo来告诉他们为什么。
我看了一下这个demo,确实说明了这个问题,但我认为不够直观,呵呵,于是我就稍微的改了一下。
这是剑过不留痕的demo
using System;using System.Threading; namespace SingletonPattern{ class Program { static Thread[] threads; static void Main(string[] args) { int threadsCapacity; Console.WriteLine("请输入开启的线程数:"); string s; do { s = Console.ReadLine(); if (!int.TryParse(s, out threadsCapacity)) { Console.WriteLine("数字格式不正确,请输入开启的线程数:"); continue; } else if (1 > threadsCapacity) { Console.WriteLine("数字应不小于 1,请输入开启的线程数:"); continue; } else { break; } } while (true); threads = new Thread[threadsCapacity]; Program pg = new Program(); for (int i = 0; i < threads.Length; i++) { Thread thread = new Thread(new ThreadStart(Singleton.GetIns)); thread.Name = "线程 " + i; threads[i] = thread; } for (int i = 0; i < threads.Length; i++) { threads[i].Start(); } Console.ReadKey(); } } class Singleton { private static Singleton instance; private static object _lock = new object(); private static int instanceQuantity = 0; private Singleton() { } public static Singleton GetInstance() { if (instance == null) { // 挂起线程,确保所有的线程都执行到这并等待 Thread.Sleep(1000); lock (_lock) { //if (instance == null) //{ // instance = new Singleton(); // ++instanceQuantity; // Console.WriteLine(Thread.CurrentThread.Name + " 生成第 " + instanceQuantity + " 实例!"); //} instance = new Singleton(); ++instanceQuantity; Console.WriteLine(Thread.CurrentThread.Name + " 生成第 " + instanceQuantity + " 实例!"); } } return instance; } public static void GetIns() { GetInstance(); } }}
下面是我修改过得demo,修改的地方主要在GetInstance()这个方法内部,其他地方没动,所以我只贴出修改代码的地方,免得占空间!
public static Singleton GetInstance() { if (instance == null) { // 挂起线程,确保所有的线程都执行到这并等待 Console.WriteLine("我是" + Thread.CurrentThread.Name + " ,instance等于null,哦,对象还没创建呢,看来我有机会哦!"); Thread.Sleep(1000); lock (_lock) { Console.WriteLine("我是" + Thread.CurrentThread.Name + " ,instance等于null,哈哈,我锁,我是第一个到的!创建对象的任务就交给我了!"); if (instance == null) { instance = new Singleton(); ++instanceQuantity; Console.WriteLine("我是" + Thread.CurrentThread.Name + " ,哼哼,对象是我创建的!"); } else { Console.WriteLine("我是"+Thread.CurrentThread.Name + ",虽然我之前判断instance等于null,但现在判断的时候,却不等null了,唉,还是被别人快了一步!不过好在我判断了,要不就多创建了一个,失去了单例模式的意义!"); } //Console.WriteLine(Thread.CurrentThread.Name + " 生成第 " + instanceQuantity + " 实例!"); //instance = new Singleton(); //++instanceQuantity; //Console.WriteLine(Thread.CurrentThread.Name + " 生成第 " + instanceQuantity + " 实例!"); } } return instance; }
下面是运行的结果,多运行几遍就可能出现这个结果了。
文字描述:
虽然线程0先进的第一个if,但创建对象的确实线程1,而此时,线程0已经判断了instance==null,所以他还会再创建一个对象,因为并没有人告诉线程0,线程1已经创建过对象了,而内部的这个if,就是为了告诉别人,对象我已经创建过了!其他人就不要再创建了,不知道我这样解释,清楚不!
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。