在应用中有很多实例可能需要延迟创建对象, 比如设计模式中的单例模式就是一种非常常见的情况.如果不考虑线程安全我们通常会编写如下代码:

public class SingleInstance
{
private static SingleInstance instance;
private SingleInstance()
{
} public static SingleInstance Instance
{
get
{
if (instance == null)
{
instance = new SingleInstance();
} return instance;
}
}
}

如果我们想让其可以在多线程环境下运行, 那么我们升级一下此使用double check的方式去避免线程间创建多个示例. 代码如下:


public class SingleInstance
{
private static SingleInstance instance;
private static object lockObj = new Object();
private SingleInstance()
{
} public static SingleInstance Instance
{
get
{
if (instance == null)
{
lock (lockObj)
{
if (instance == null)
{
instance = new SingleInstance();
}
}
} return instance;
}
}
}

以上代码在并非真的是线程安全了, 因为在IA64CPU架构上,会存在返回null的可能. 所以我们使用关键字volatile来修饰一下instance对象(volatile的作用就是添加内存栅栏fence), 代码就变成了

public class SingleInstance
{
private static volatile SingleInstance instance;
private static object lockObj = new Object();
private SingleInstance()
{
} public static SingleInstance Instance
{
get
{
if (instance == null)
{
lock (lockObj)
{
if (instance == null)
{
instance = new SingleInstance();
}
}
} return instance;
}
}
}

看上去挺不错的了. 就是代码有点长了, .NET为我们提供了Lazy对象为我们解决了创建此类对象的机制. 修改后代码如下:

public class SingleInstance
{
private static Lazy<SingleInstance> SingleInstanceFacotry = new Lazy<SingleInstance>(()=> new SingleInstance(), true); private SingleInstance()
{
} public static SingleInstance Instance
{
get
{
return SingleInstanceFacotry.Value;
}
}
}

Lazy的构造函数中可以方便的设置是否需要线程安全.

这样每次都要有个Lazy来辅助, .NETBCL的设计者还提供了另外一种模式, 使用LazyInitializer来保证线程是安全的.示例代码如下:

public class SingleInstance
{
private static SingleInstance instance; private SingleInstance()
{
} public static SingleInstance Instance
{
get
{
LazyInitializer.EnsureInitialized(ref instance, ()=> new SingleInstance());
return instance;
}
}
}

这种方式的好处是, 你在原来的非线程安全重构到线程安全更新的代码最少.

.NET下的延迟加载的更多相关文章

  1. Hibernate之lazy延迟加载

    一.延迟加载的概念 当Hibernate从数据库中加载某个对象时,不加载关联的对象,而只是生成了代理对象,获取使用session中的load的方法(在没有改变lazy属性为false的情况下)获取到的 ...

  2. EF 延迟加载和预先加载

    最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精   本节探讨延迟加载和预先加载 Entity Frame ...

  3. Hibernate检索策略之延迟加载和立即加载

    延迟加载:延迟加载(lazy load懒加载)是当在真正需要数据时,才执行SQL语句进行查询.避免了无谓的性能开销. 延迟加载分类:  1.类级别的查询策略 2.一对多和多对多关联的查询策略 3.多对 ...

  4. Hibernate之lazy延迟加载(转)

    一.延迟加载的概念 当Hibernate从数据库中加载某个对象时,不加载关联的对象,而只是生成了代理对象,获取使用session中的load的方法(在没有改变lazy属性为false的情况下)获取到的 ...

  5. EF如何操作内存中的数据和加载外键数据:延迟加载、贪婪加载、显示加载

    EF如何操作内存中的数据和加载外键数据:延迟加载.贪婪加载.显示加载 之前的EF Code First系列讲了那么多如何配置实体和数据库表的关系,显然配置只是辅助,使用EF操作数据库才是每天开发中都需 ...

  6. Linq的延迟加载问题

    什么是延迟加载:所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作.可以简单理解为,只有在使用的时候,才会发出sql语句进行查询,数据是分N次读取. 什么是立即加载:所谓立即加载既是所有的 ...

  7. iframe弹出框js ie6下存在bug

    ie6的iframe在第一次加载的显示不出来,显示空白,但是很奇怪,刷新就可以正常显示了,一开始以为这只是IE6下iframe加载的bug,但是最后结果发现这是ie6下javascript延迟加载出现 ...

  8. Entity Framework 4.1 : 贪婪加载和延迟加载

    这篇文章将讨论查询结果的加载控制. EF4.1 允许控制对象之间的关系,当我们进行查询的时候,哪些关系的数据将会被加载到内存呢?所有相关的对象都需要吗?在一些场合可能有意义,例如,当查询的实体仅仅拥有 ...

  9. Mybatis延迟加载的实现以及使用场景

    首先我们先思考一个问题,假设:在一对多中,我们有一个用户,他有100个账户. 问题1:在查询用户的时候,要不要把关联的账户查出来? 问题2:在查询账户的时候,要不要把关联的用户查出来? 解答:在查询用 ...

随机推荐

  1. C语言中strcpy(char *strDest, const char *strScr)字符串复制库函数的理解与分析

    1.原版的strcpy()函数原型 char * strcpy( char *strDest, const char *strSrc ) { assert( (strDest != NULL) &am ...

  2. Java [Leetcode 234]Palindrome Linked List

    题目描述: Given a singly linked list, determine if it is a palindrome. Follow up:Could you do it in O(n) ...

  3. 【Unity3D】自动寻路(Nav Mesh Agent组件)

    1.首先添加场景模型 2.为场景模型(寻路路径)添加NavMesh渲染,操作:Windows->Navigation->勾选Navigation Static选项->不勾选Gener ...

  4. Ejabberd源码解析前奏--管理

    一.ejabberdctl 使用ejabberdctl命令行管理脚本,你可以执行ejabberdctl命令和一些普通的ejabberd命令(后面会详细解说).这意味着你可以在一个本地或远程ejabbe ...

  5. Mybaits+SpringMVC项目(含代码生成工具源码)

       大家下载下来修改数据库配置应该就能运行起来,里面有一个SM的简单案例了,还有说明文件. 运行效果    工具类可以生成Springmvc+mybatis的相关类和配置文件,并具有增删查改的功能, ...

  6. 云计算服务模型,第 3 部分: 软件即服务(PaaS)

    英文原文:Cloud computing service models, Part 3: Software as a Service 软件即服务 (SaaS) 为商用软件提供基于网络的访问.您有可能已 ...

  7. TestNG官方文档中文版(2)-annotation(转)

    1. 介绍    TestNG是一个设计用来简化广泛的测试需求的测试框架,从单元测试(隔离测试一个类)到集成测试(测试由有多个类多个包甚至多个外部框架组成的整个系统,例如运用服务器). 编写一个测试的 ...

  8. 使用libzplay库封装一个音频类

    装载请说明原地址,谢谢~~      前两天我已经封装好一个duilib中使用的webkit内核的浏览器控件和一个基于vlc的用于播放视频的视频控件,这两个控件可以分别用在放酷狗播放器的乐库功能和MV ...

  9. asp.net中遍历界面上所有控件进行属性设置

    * 使用方法: *  前台页面调用方法,重置:    protected void Reset_Click(object sender, EventArgs e)        {           ...

  10. new trip

    离开YY已经快一周了,特别感谢以前的老大姚冬和朱云峰,从他俩身上学到了很多.这个决定也经过了很长的纠结,不想再做个犹豫不决的人,所以最后还是坚定了最初的信念,也算是对半年前自己的一个完好交代,以防将来 ...