.NET下的延迟加载
2024-09-01 07:03:23
在应用中有很多实例可能需要延迟创建对象, 比如设计模式中的单例模式就是一种非常常见的情况.如果不考虑线程安全我们通常会编写如下代码:
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;
}
}
}
这种方式的好处是, 你在原来的非线程安全重构到线程安全更新的代码最少.
最新文章
- Burp Suite新手指南
- Beginning Scala study note(8) Scala Type System
- 使用css使textbox输入内容自动变大写
- PPP协议
- Activity中获取当前Fragment 中的子控件
- asp.net 有关时间各种(输出)处理
- 【转】C++标准库和标准模板库
- 连接mysql问题 mysqlnd cannot connect to MySQL 4.1+ using old authentication
- pyvcf 模块
- Python 统计代码行
- ajax使用jsonp解决跨域问题
- 鼠标事件之鼠标滑过事件MOUSEOVER
- Python 解LeetCode:Intersection of Two Arrays
- Python案例分享
- JLOI2018 划水中...
- 从 RAID 到 Hadoop Hdfs 『大数据存储的进化史』
- [swarthmore cs75] Compiler 6 – Fer-de-lance
- qt 中的基本知识
- Swift5 语言参考(九) 泛型和参数
- MAC下安装Homebrew 和 @权限的问题