惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
Microsoft Azure Blog
Microsoft Azure Blog
月光博客
月光博客
S
Securelist
J
Java Code Geeks
Recorded Future
Recorded Future
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
M
MIT News - Artificial intelligence
S
Secure Thoughts
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
D
Docker
Martin Fowler
Martin Fowler
The Last Watchdog
The Last Watchdog
WordPress大学
WordPress大学
The GitHub Blog
The GitHub Blog
Vercel News
Vercel News
O
OpenAI News
www.infosecurity-magazine.com
www.infosecurity-magazine.com
博客园_首页
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
PCI Perspectives
PCI Perspectives
N
News and Events Feed by Topic
H
Heimdal Security Blog
SecWiki News
SecWiki News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
博客园 - 【当耐特】
T
Troy Hunt's Blog
L
LINUX DO - 最新话题
Hacker News: Ask HN
Hacker News: Ask HN
Hacker News - Newest:
Hacker News - Newest: "LLM"
N
Netflix TechBlog - Medium
A
Arctic Wolf
The Hacker News
The Hacker News
I
Intezer
S
Schneier on Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Apple Machine Learning Research
Apple Machine Learning Research
L
Lohrmann on Cybersecurity
宝玉的分享
宝玉的分享
P
Privacy & Cybersecurity Law Blog
Stack Overflow Blog
Stack Overflow Blog
T
Tor Project blog
小众软件
小众软件
Simon Willison's Weblog
Simon Willison's Weblog
The Cloudflare Blog
Jina AI
Jina AI

博客园 - Franz

从如此简单的代码谈起 谈谈C#基元类型 TFS代码签入指导 并发之阿喀琉斯之踵 SmallDateTime时间范围检查 too many automatic redirections were attempted 预览Cube出现没有注册类错误 Transaction Manager Maximum Timeout 我的VisualStudio工具箱 简单的谈一下.NET下的AOP TFS上使用Beyond Compare来比较源码 SqlBulkCopy 是个好对象 释放Sql Server内存 吐槽一下Silverlight的SaveFileDialog. 书评《模式-工程化实现及扩展》 定义加载动画 代码共享的小技巧 WPF将控件保存为图片 《编程人生》的书评
.NET下的延迟加载
Franz · 2013-07-04 · via 博客园 - Franz

2013-07-04 13:06  Franz  阅读(284)  评论()    收藏  举报

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

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

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