无锁,线程安全,延迟加载的单例实现(C#)
单例(singleton)是非常常见,也非常有用的设计模式,当然了, 面试中也是经常会被问到的:)在几乎所有的项目中都能看到它的身影。简而言之,单例保证了一个自定义类型在整个程序的生命周期只被创建一次。要实现一个简单的单例是也很容易的:
public class Example
{
private static Example instance; private Example()
{
} public static Example Instance
{
get
{
if (instance != null)
{
instance = new Example();
} return instance;
}
}
}
这是大多数人的写法。
这是一个延迟加载的单例。换句话说,只有当调用Example.Instance时,才会创建Example的实例。当不存在多线程调用的情况下,这个单例是工作得很好的。但是在现实中,我们已经很少不去考虑线程安全了。提到线程安全,我们第一反应就是加锁:
public class Example
{
private static Example instance; private object myLock = new object(); private Example()
{
} public static Example Instance
{
get
{
lock(myLock)
{
if (instance != null)
{
instance = new Example();
} return instance;
}
}
}
}
这显然是没有问题的,我相信也是大多数程序员的做法。
在面试中如果面试者能够在没有任何提示下给出这个线程安全且延迟加载的单例,已经很让面试官满意了。 可是我想再吹毛求疵下:能不能实现一个无锁的线程安全单例?
无锁且要线程安全。。。我们需要借助语言的特性。(实际上代码更少了)
public class Example
{
private static Example instance = new Example(); private Example()
{
} public static Example Instance
{
get
{
return instance;
}
}
}
的确,无锁且线程安全了,但是。。。延迟加载似乎又缺失了。也许有人要问,这个延迟加载有什么用?
绝大多数情况下,这个延迟加载没有任何用(面试虐人除外),除非这个类还有其他static public methods。譬如说这个Example类有一个静态方法:
public static string Output()
{
string str;
// process the str.
return str;
}
并且我们只会用到Example.Output()。在这种情况下如果 Example 的instance被创建了,显然是浪费内存。据我所知,这是延迟加载唯一有用的地方。
不管这个延迟加载用处有多大,我们单纯从研究的角度考虑,是否能既做到无锁,线程安全,又延迟加载?
C#语言的另一大特性帮助了我们:嵌套类。直接上代码:
public class Example
{
private static Example instance; private Example()
{
} public static Example Instance
{
get
{
return Nested.Instance;
}
} class Nested
{
static Nested()
{
} internal static readonly Example Instance = new Example();
}
}
无锁,线程安全,延迟加载的单例实现(C#)的更多相关文章
- c++:自己动手实现线程安全的c++单例类
前段时间使用c++做项目开发,需要根据根据配置文件路径加载全局配置文件,并对外提供唯一访问点.面对这样一个需求,自然的就想到了使用单例模式来创建一个单例配置对象,供外部调用.一开始想使用boost中自 ...
- iOS-主线程刷新UI【+单例】
主线程刷新UI dispatch_async(dispatch_get_main_queue(), ^{ /// }); 单例 static Tools *_sharedManger; @implem ...
- MVC 创建线程内的db单例
using System; using System.Collections.Generic; using System.Linq; using System.Web; using LSUnion.S ...
- java设计模式--解决单例设计模式中懒汉式线程安全问题
首先写个单例,懒汉模式: public class SingleDemo { private static SingleDemo s = null; private SingleDemo(){} pu ...
- 依赖注入及AOP简述(九)——单例和无状态Scope .
三.依赖注入对象的Scope及其生命周期 在前面的章节我们讲到,依赖注入容器之所以能够区别于以往的ServiceLocator等容器,是在于其不但能够自动构建多层次的.完整的依赖关系图,并且可以管理依 ...
- GOF设计模式之1:单例设计模式
1.单例设计模式核心作用: 保证一个类只有一个实例,并且提供了访问该实例的全局访问点 2.常见应用场景: window的任务管理器 项目中读取配置文件一般也是一个单例模式 数据库连接池的设计也是采用单 ...
- Java设计模式:Singleton(单例)模式
概念定义 Singleton(单例)模式是指在程序运行期间, 某些类只实例化一次,创建一个全局唯一对象.因此,单例类只能有一个实例,且必须自己创建自己的这个唯一实例,并对外提供访问该实例的方式. 单例 ...
- 十次艳遇单例设计模式(Singleton Pattern)
1.引言 单例设计模式(Singleton Pattern)是最简单且常见的设计模式之一,在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访 ...
- Java单例和多例
背景:最近在学习韩老师的笔记时候发现不是很了解单例和多例,于是通过网上查找资料的方式去学习. 设计模式:最佳的实践,是软件开发人员在软件开发过程中面临一般解决方案,也就是开发的经验总结. 单例模式(S ...
随机推荐
- window.applicationCache事件,介绍
1.关于applicationCache对象 在IE和Google中 为ApplicationCache对象 而在FF中为 OfflineResourceList对象 通过ApplicationCac ...
- [500lines]500行代码写web server
项目地址:https://github.com/aosabook/500lines/tree/master/web-server.作者是来自Mozilla的Greg Wilson.项目是用py2写成. ...
- mysql操作1
一.连接MYSQL.格式: mysql -h主机地址 -u用户名 -p用户密码1.连接到本机上的MYSQL.首先打开DOS窗口,然后进入目录mysql\bin,再键入命令mysql -u root - ...
- 利用C++ RAII技术自动回收堆内存
在C++的编程过程中,我们经常需要申请一块动态内存,然后当用完以后将其释放.通常而言,我们的代码是这样的: 1: void func() 2: { 3: //allocate a dynamic me ...
- 我的github代码添加
1.创建一个新的repository: echo "# backupVim" >> README.md git init git add README.md git c ...
- JQuery中$.ajax()方法参数
url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. type: 要求为String类型的参数,请求方式(post或get)默认为get.注意其他http请求方法,例如put和 ...
- C语言对数组取地址
#include <stdio.h> main() { ] = {,,,,}; printf("a=%p\n" , a); printf("a=%p\n&qu ...
- Python 函数传递list,传递dict 以及*args和**kargs
函数之间传递list: def show(ll): for i in ll: print(i) show(['chen','hang','wang','yadan']) #============== ...
- C# 代码中 计算某个函数 或WebService 请求花费时间
/// 计算请求所花费的时间 System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start( ...
- svn , github工作流
svn 需要有一台中央服务器,所有的分支,主干,标签,全都保存在这台中央服务器上.开发着需要提交代码时,需要保持中央服务器连接.切换分支时会有本地与服务器网络连接. git 改进了这一点,每台安装有g ...