用两个小样例来解释单例模式中的“双重锁定”

学习单例模式时,好多人都不太理解双重锁定

学完后突然想到一个非常有趣的样例。

单例模式结构图:

代码:

Singleton类

    class Singleton
    {
        private static Singleton instance;
        private static readonly object syncRoot = new object();  //程序执行时创建一个静态仅仅读的进程辅助对象
        private Singleton() { }                 //用private修饰构造方法,防止外界利用new创建此类实例
        public static Singleton GetInstance()
        {
            if (instance == null)               //若instance对象为null,则继续
            {
                lock (syncRoot)                 //↓↓↓↓在同一时刻加了锁的这部分程序仅仅有一个线程能够进入↓↓↓↓
                {
                    if (instance == null)//假设instance对象为null,则为它分配实例
                    {
                        instance = new Singleton();
                    }
                }                               //↑↑↑↑在同一时刻加了锁的这部分程序仅仅有一个线程能够进入↑↑↑↑
            }
            return instance;
        }
    }

client代码

    static void Main(string[] args)
    {
        Singleton singleton1=Singleton.GetInstance();
        Singleton singleton2=Singleton.GetInstance();
        //……
    }

说明:

《大话设计模式》中,小菜问道:“我在外面已经推断了instance实例是否存在。为什么在lock里面还要做一次instance实例是否存在的推断呢?”

大鸟是这么回答的:当instance为null而且同一时候有两个线程调用GetInstance方法时。他们将都能够通过第一重instance==null的推断。

然后因为lock机制。这两个线程则仅仅有一个进入。另外一个在外排队等候,必需要当中的一个进入并出来后,还有一个才干进入,而此时假设没有了第二重的instance是否为null的推断,则第一个线程创建了实例,第二个线程还是能够继续再创建新的实例,这就没有达到单例的目的。

假设认为大鸟的话不太好理解。能够看看这个样例:

 ——假设我和你妈掉进河里,你先救谁?——当然救我妈。宁愿睡沙发!

在一个200元时装店(顾名思义,全部的衣服都是200元),妈妈看中一件200元的衣服,媳妇也看中一件200元的衣服。但我仅仅有200块钱(所以仅仅能买一件),虽然如此,作为儿子和丈夫的我也得掏钱啊。

【PS:此处相当于代码中的client调用,singleton1为给老妈买衣服,singleton2为给媳妇买衣服】

我走进商店时,跟店员说。我想买衣服,店员说:“那你有200快钱吗?没钱就赶紧出去!

”。【PS:此处为第一层推断】

经过深思熟虑,百善孝为先,我买了老妈看中的那件衣服。【给老妈买衣服的线程成功运行。给媳妇买衣服的线程被锁在外面】

那媳妇的衣服怎么办?踱来踱去还想买还有一件时。店员问我:“你有200块钱吗?没钱就赶紧出去!

”于是我出去了。

【PS:第二层推断,我没钱了,所以出去了,今晚回去肯定又得睡沙发了T_T…T_T…T_T】

讲完这个故事,突然又想到一件事,就再啰嗦几句,爆爆料。

打倒花心大萝卜!

大家都听说过Darry Ring钻戒。它的宗旨是“用一生给你一个唯一的承诺”,即一个男人一生仅仅能凭身份证买一个。

话说几十年前看上一位美丽的女子。为了表达爱慕,为她买了一枚Darry Ring。女子被感动,顺利追到手,当时还纳闷为什么买钻戒还要填写身份证号,只是也没在意。前几天又看上一女子,于是花心的我想脚踏两条船。想再买一枚Darry Ring追求之。麻烦来了。买钻戒的时候,工作人员告诉我说,我已经买过Darry Ring的戒指。而一个男人一生仅仅能凭身份证买一枚……我去。什么鸟规定!于是忍痛挥泪和女神说拜拜T_T…T_T…T_T

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHV5dXlhbmc2Njg4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >

时间: 2024-08-25 11:29:20

用两个小样例来解释单例模式中的“双重锁定”的相关文章

用两个小例子来解释单例模式中的“双重锁定”

学习单例模式时,好多人都不太理解双重锁定.学完后突然想到一个很有趣的例子. 单例模式结构图: 代码: Singleton类 class Singleton { private static Singleton instance; private static readonly object syncRoot = new object(); //程序运行时创建一个静态只读的进程辅助对象 private Singleton() { } //用private修饰构造方法,防止外界利用new创建此类实例

单例模式中 的 双重检查锁 概念与用法

public class Singleton { //私有的 静态的 本类属性 private volatile static Singleton _instance; //私有化构造器 private Singleton() {} /* * 1st version: creates multiple instance if two thread access * this method simultaneouslyX */ public static Singleton getInstance

SpringMVC+Spring+Hibernate的小样例

Strusts2+Spring+Hibernate尽管是主流的WEB开发框架,可是SpringMVC有越来越多的人使用了.确实也很好用.用得爽! 这里实现了一个SpringMVC+Spring+Hibernate的小样例.凝视都在代码里面. 项目各包的结构例如以下图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWlhbnR1amF2YQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve

C Tips:显示点阵汉字的小样例

非常简陋的一段小程序,演示怎样显示点阵字库.有时间的时候再详解. #include <stdio.h> #include <stdlib.h> struct HzkInfoStruct { int HzkSelect; int HzkSquare; char * fileName; FILE * file; int martixBytesCount; unsigned char *pMatrix; }; typedef struct HzkInfoStruct HzkInfo; v

用Javascript取float型小数点后两位,例22.127456取成22.13,如何做?

1. 最笨的办法....... [我就怎么干的.........] 1function get()2{3    var s = 22.127456 + "";4    var str = s.substring(0,s.indexOf(".") + 3);5    alert(str);6} 2. 正则表达式效果不错 1<script type="text/javascript">2onload = function(){3    v

单例模式中的线程安全(延迟加载)

设计模式中常用的单例模式,在jvm中可以保证该对象只有一个实例存在.这样对于一些特别大的对象,可以很好的节省资源.由于省去了new,所以节省了gc消耗.同时,对于一些核心系统逻辑,可以能要一个对象实例来控制会省去很多麻烦. 单例模式,如果不考虑多线程,则可以如下创建 public class Singleton { /* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */ private static Singleton instance = null; /* 私有构造方

单例模式、双检测锁定DCL、volatile详解

单例模式最要关心的则是对象创建的次数以及何时被创建. Singleton模式可以是很简单的,它的全部只需要一个类就可以完成(看看这章可怜的UML图).但是如果在"对象创建的次数以及何时被创建"这两点上较真起来,Singleton模式可以相当的复杂,比头五种模式加起来还复杂,譬如涉及到DCL双锁检测(double checked locking)的讨论.涉及到多个类加载器(ClassLoader)协同时.涉及到跨JVM(集群.远程EJB等)时.涉及到单例对象被销毁后重建等.对于复杂的情况

Java单例模式中双重检查锁的问题

单例创建模式是一个通用的编程习语.和多线程一起使用时,必需使用某种类型的同步.在努力创建更有效的代码时,Java 程序员们创建了双重检查锁定习语,将其和单例创建模式一起使用,从而限制同步代码量.然而,由于一些不太常见的 Java 内存模型细节的原因,并不能保证这个双重检查锁定习语有效. 它偶尔会失败,而不是总失败.此外,它失败的原因并不明显,还包含 Java 内存模型的一些隐秘细节.这些事实将导致代码失败,原因是双重检查锁定难于跟踪.在本文余下的部分里,我们将详细介绍双重检查锁定习语,从而理解它

单例模式、双检测锁定DCL、volatile(转)

单例模式最要关心的则是对象创建的次数以及何时被创建. Singleton模式可以是很简单的,它的全部只需要一个类就可以完成(看看这章可怜的UML图).但是如果在“对象创建的次数以及何时被创 建”这两点上较真起来,Singleton模式可以相当的复杂,比头五种模式加起来还复杂,譬如涉及到DCL双锁检测(double checked locking)的讨论.涉及到多个类加载器(ClassLoader)协同时.涉及到跨JVM(集群.远程EJB等)时.涉及到单例对象被销毁后重建 等.对于复杂的情况,本章