.NET下的延迟加载
2013-07-04 13:06 Franz 阅读(277) 评论(0) 收藏 举报在应用中有很多实例可能需要延迟创建对象, 比如设计模式中的单例模式就是一种非常常见的情况.如果不考虑线程安全我们通常会编写如下代码:
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
public class SingleInstance
{
private static SingleInstance instance;
private SingleInstance()
{
}
public static SingleInstance Instance
{
get
{
LazyInitializer.EnsureInitialized(ref instance, ()=> new SingleInstance());
return instance;
}
}
}
这种方式的好处是, 你在原来的非线程安全重构到线程安全更新的代码最少.
浙公网安备 33010602011771号