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

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;
}
}
}

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

最新文章

  1. Burp Suite新手指南
  2. Beginning Scala study note(8) Scala Type System
  3. 使用css使textbox输入内容自动变大写
  4. PPP协议
  5. Activity中获取当前Fragment 中的子控件
  6. asp.net 有关时间各种(输出)处理
  7. 【转】C++标准库和标准模板库
  8. 连接mysql问题 mysqlnd cannot connect to MySQL 4.1+ using old authentication
  9. pyvcf 模块
  10. Python 统计代码行
  11. ajax使用jsonp解决跨域问题
  12. 鼠标事件之鼠标滑过事件MOUSEOVER
  13. Python 解LeetCode:Intersection of Two Arrays
  14. Python案例分享
  15. JLOI2018 划水中...
  16. 从 RAID 到 Hadoop Hdfs 『大数据存储的进化史』
  17. [swarthmore cs75] Compiler 6 – Fer-de-lance
  18. qt 中的基本知识
  19. Swift5 语言参考(九) 泛型和参数
  20. MAC下安装Homebrew 和 @权限的问题

热门文章

  1. malloc、free的使用
  2. json化表单数据
  3. UVA 10098 Generating Fast, Sorted Permutation
  4. Tomcat 调优总结
  5. FTP文件上传与下载
  6. Hadoop序列化
  7. awk简单使用『摘.非原创』
  8. Survival(ZOJ 2297状压dp)
  9. HDU 5750 Dertouzos 简单数学
  10. 精雕细琢 35 套精美的 PSD 图标素材