在.NET 4.0之后,.NET Framework中提供了一种安全的延迟加载类型Lazy
Lazy能够在多线程环境下,保证GetValue函数只执行一次,从而实现单例模式

在过去,实现单例模式我们通常使用二次判断锁,或者利用类的静态初始化函数
利用Lazy类型,能够简化这一过程,并且性能上更好

Lazy创建的时候可以指定线程安装模式,目前有两种模式,PublicationOnly,ExcutionAndPublication

PublicationOnly模式

                boxed = CreateValue(); //1if (boxed == null ||Interlocked.CompareExchange(ref m_boxed, boxed, null) != null) //2
                {boxed = (Boxed)m_boxed; //3
                }else{m_valueFactory = ALREADY_INVOKED_SENTINEL; //4}

1.运行初始化函数,装箱到一个内部Box类型中,解决null值判断的问题,如果已经创建的情况,会返回null,该过程是线程不安全的

2.判断m_boxed是否为空,m_boxed是value保存的字段,如果等于空则设置为boxed,该方法能保证原子性,该过程是线程安全的

3.如果CreateValue返回空,表示其他线程已经创建有实例,则设置为已经创建好的实例

4.将初始化方法标记为已经初始化,一般发生在并发运行情况下,多次运行CreateValue

PublicationOnly模式下使用基于Interlocked.CompareExchange实现的乐观锁,该类包含了原子性方法 CAS(Compare and swap)

CAS是利用CPU提供的原子性指令来实现,不同运行时版本可能有不一样实现
Interlocked具体的实现在Native方法中,有兴趣的朋友可以通过coreclr/jvm代码查看具体实现

这种模式下,单例函数可能多次运行,但是最终能保证获取到的实例只有一个

ExcutionAndPublication模式下使用的是Volatile+MonitorMonitor就是lock语句的实现,Monitor实现在Native代码中,是重量级的锁

Monitor支持队列和线程睡眠,能够保证一整个方法块处于单线程执行状态

                object threadSafeObj = Volatile.Read(ref m_threadSafeObj); //强制从主内存空间同步变量到线程内存空间副本bool lockTaken = false;try{if (threadSafeObj != (object)ALREADY_INVOKED_SENTINEL) //此时会有多个线程获取到正确值,抢夺开始Monitor.Enter(threadSafeObj, ref lockTaken); //尝试等待锁,进入成功设置lockTaken为trueelseContract.Assert(m_boxed != null);//单线程代码块 Startif (m_boxed == null) //没有设置值的情况{boxed = CreateValue(); //获取值m_boxed = boxed; //设置到字段中Volatile.Write(ref m_threadSafeObj, ALREADY_INVOKED_SENTINEL); //强制将线程内存空间副本写入到主内存空间}else // got the lock but the value is not null anymore, check if it is created by another thread or faulted and throw if so
                    {boxed = m_boxed as Boxed;if (boxed == null) // it is not Boxed, so it is a LazyInternalExceptionHolder
                        {LazyInternalExceptionHolder exHolder = m_boxed as LazyInternalExceptionHolder;Contract.Assert(exHolder != null);exHolder.m_edi.Throw();}}            //单线程代码块End}finally{if (lockTaken) //进入成功需要释放,避免死锁Monitor.Exit(threadSafeObj);}

转载于:https://www.cnblogs.com/Gool/p/9420870.html

线程安全单例最佳实践,C#中的Lazy是如何保证线程安全的相关推荐

  1. java中的单例_细说Java中的几种单例模式

    在Java中,单例模式分为很多种,本人所了解的单例模式有以下几种,如有不全还请大家留言指点: 饿汉式 懒汉式/Double check(双重检索) 静态内部类 枚举单例 一.饿汉式 image 饿汉式 ...

  2. C++ 九阴真经之线程安全单例类

    C++ 九阴真经之线程安全单例类 与之前的单例类似,但普通的单例类是非线程安全的,就是是你不能有些线程读,有些线程写,一般来说,要安全访问单例,就需要用户自己加载来控制对单例的访问. 日常开发中经常会 ...

  3. android 单例的作用,Android中单例模式的几个坑

    先来看这样一个单例,稍微有点经验的同学可能都会说,这样的单例是非线程安全的.要加个volatile关键字才可以.class Singleton{        private static  Sing ...

  4. 单例设计模式在Spring中的应用

    一.实现一个单例 可以使用如下的步骤实现一个单例类: 单例设计模式的实现流程 1.将构造方法私有化,使用private关键字修饰.使其不能在类的外部通过new关键字实例化该类对象. 2.在该类内部产生 ...

  5. android 源码中的单例,Android源码中的一种单例实现

    单例模式的实现方式有懒汉,饿汉,双重校验锁,枚举,内部类等等,写法就不全部列举了.Android源码中有一个单例辅助类/frameworks/base/core/java/android/util/S ...

  6. SpringBean默认是单例的,高并发情况下,如何保证并发安全?

    以下文章来源方志朋的博客,回复"666"获面试宝典 Spring的bean默认都是单例的,某些情况下,单例是并发不安全的,以Controller举例,问题根源在于,我们可能会在Co ...

  7. 移动端 UI 适配最佳实践(中)

    为什么80%的码农都做不了架构师?>>>    上篇谈到了一些基础概念:屏幕密度.逻辑像素什么的,接下来继续探讨 常见设备尺寸 更全的数据请参考Google 统计 说明:图中的 iP ...

  8. 反射和内省_单例设计模式–内省和最佳实践

    反射和内省 定义: Singleton是" 四人帮"设计模式的一部分,它属于创新设计模式. 在本文中,我们将更深入地研究Singleton模式的用法. 就建模而言,它是最简单的设计 ...

  9. 单例设计模式–内省和最佳实践

    定义: Singleton是" 四人帮"设计模式的一部分,它属于创新设计模式. 在本文中,我们将更深入地研究Singleton模式的用法. 就建模而言,它是最简单的设计模式之一,但 ...

最新文章

  1. 解决 Git: There is no tracking information for the current branch.的问题
  2. Perl中的字符串操作函数
  3. dhl: js判断网页对象是否存在
  4. (转)几种常用存储过程分页方法
  5. virsh 关机_kvm虚拟机不能使用virsh shutdownw命令关闭虚拟机的解决方法
  6. java弹窗 触发事件_关于ElementUI中MessageBox弹框的取消键盘触发事件(enter,esc)关闭弹窗(执行事件)的解决方法...
  7. python第一步怎么写_python第一步
  8. 【Elasticsearch】 Elasticsearch并发冲突问题
  9. python自学-Python 应该怎么学?
  10. go - str - byte
  11. hdu 1983(BFS+DFS) 怪盗Kid
  12. 为啥mysql的load这么快_【MySQL】浅谈MySQL的LOAD DATA
  13. 蚂蚁的开放:想办法摸到10米的篮筐 1
  14. work_study_plan
  15. Stata-DEA:数据包络分析一文读懂
  16. jsonViewer json格式化工具
  17. 2019学位计算机模拟试题,2019年下半年成人学位英语模拟试题1
  18. 力扣(66.67)补8.27
  19. 从区块链到DAG(五)--DAG项目介绍IOTA和Obyte
  20. CVPR_2021_Fast-GANFIT: Generative Adversarial Networkfor High Fidelity 3D Face Reconstruction

热门文章

  1. mysql数据表的字段操作
  2. utility_VS2015基本操作
  3. SaltStack 模块学习之拷贝master服务器上文件和目录到minion服务器
  4. T-SQL select语句连接两个表
  5. 算法导论( FFT 自动机 最优二叉搜索树 !!!)
  6. 如何搭建个人独立博客
  7. AndroidStudio_从Eclipse到AndroidStudio开发工具_认识使用AndroidStudio_导入用eclipse开发的工程---Android原生开发工作笔记69
  8. MQTT工作笔记0006---CONNECT控制报文3
  9. Polyfill工作笔记001---简介
  10. 微信小程序开发学习笔记001--认识微信小程序,第一个微信小程序