singleton pattern的推荐实现
一、单例模式的C#实现:
(1)使用double-checked locking的方式:
public sealed class Singleton
{
private static volatile Singleton instance = null;
private static readonly object padlock = new object(); private Singleton()
{
} public static Singleton Instance
{
get
{
if (instance==null)
{
lock (padlock)
{
if (instance==null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
}
这种实现方式对多线程来说是安全的,同时线程不是每次都加锁,只有判断对象实例没有被创建时它才加锁。注意volatile的使用,只有加了volatile修饰,才能保证在多线程环境下只有一个实例。
因为使用了锁,没有下面的方式高效。
public sealed class Singleton
{
private static Singleton instance = null; private Singleton()
{
} public static Singleton GetInstance()
{
if(instance!=null) return instance; Singleton temp = new Singleton();
Interlocked.CompareExchange(ref instance,temp,null); return instance;
}
}
如果多个线程同时调用GetInstance(),会产生多个Singleton对象,但是Interlocked.CompareExchange()会保证只有一个引用赋值给instance,没有引用到的对象会被垃圾回收。
(2)使用静态成员初始化方式(thread-safe without using locks)
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton(); // Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Singleton()
{
} private Singleton()
{
} public static Singleton Instance
{
get
{
return instance;
}
}
}
由于Instance是static的,保证在AppDomain只有一个实例。
初始化的线程安全性是由.Net保证的。
手动加上一个static的constructor,以让.Net对它进行延迟加载,但并不是完全延迟初始化,当该单例有其他static成员被使用时,该instance就被创建,而不是该instance被使用时才被创建。
(3)推荐方式:使用内部一个Instance的Holder来“持有”单例
public sealed class Singleton
{
private Singleton()
{
} public static Singleton Instance
{
get
{
return Nested.instance;
}
} class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
} internal static readonly Singleton instance = new Singleton();
}
}
这种实现方式不需要加锁(without using locks)。
这种方式是完全延迟初始化(fully lazy instantiation),该Instance只有被使用时才被创建。
(4)最简单有效方式:
/// <summary>
/// .NET 4's Lazy<T> type
/// </summary>
public sealed class Singleton
{
private static readonly Lazy<Singleton> lazy =
new Lazy<Singleton>(() => new Singleton()); public static Singleton Instance { get { return lazy.Value; } } private Singleton()
{
}
}
这种方式的简单和性能良好,而且还提供检查是否已经创建实例的属性IsValueCreated。
二、单例模式的Java实现:
(1)使用double-checked locking的方式:
public class Singleton {
private static volatile Singleton instance = null;
private Singleton() { }
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
双重检验锁模式(double checked locking pattern), 是一种使用同步块加锁的方法。程序员称其为双重检查锁,因为会有两次检查 instance == null ,一次是在同步块外,一次是在同步块内。 为什么在同步块内还要再检验一次?因为可能会有多个线程一起进入同步块外的 if, 如果在同步块内不进行二次检验的话就会生成多个实例了。
注意:这里的volatile修饰是必不可少的,当一个变量被volatile修饰后, 它将具备两种特性:
1. 线程可见性:当一个线程修改了被volatile修饰的变量后,无论是否加锁,其它线程都可以立即看到最新的修改,而普通变量却做不到这点;
2. 禁止指令重排序优化:普通的变量仅仅保证在该方法的执行过程中所有依赖赋值结果的地方都能获取正确的结果,而不能保证变量赋值操作的顺序与程序代码的执行顺序一致。
(2)使用Eager initialization的方式:
public class Singleton
{
private static final Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() {
return instance;
}
}
(3)推荐实现:Initialization On Demand Holder Idiom
public class Singleton
{
// Private constructor prevents instantiation from other classes
private Singleton() { } /**
* SingletonHolder is loaded on the first execution of Singleton.getInstance()
* or the first access to SingletonHolder.INSTANCE, not before.
*/
private static class SingletonHolder {
private static final Singleton instance = new Singleton();
} public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
这种写法仍然使用JVM本身机制保证了线程安全问题,由于 SingletonHolder 是私有的,除了getInstance()之外没有办法访问它,因此它是Lazy Initialized的,同时读取实例的时候不会进行同步,没有性能缺陷,也不依赖 JDK 版本。
(4)最简单实现:使用一个enum来实现,线程安全性由JVM保证。
public enum SingletonEnum {
Instance;
private SingletonEnum()
{
// Some initialize code
}
}
可以通过SingletonEnum.Instance来访问实例,这比调用getInstance()方法简单多了。 创建枚举默认就是线程安全的,所以不需要担心double checked locking, 而且还能防止反序列化导致重新创建新的对象。
参考:
http://en.wikipedia.org/wiki/Singleton_pattern
http://www.yoda.arachsys.com/csharp/singleton.html
http://www.cnblogs.com/rush/archive/2011/10/30/2229565.html
http://javarevisited.blogspot.gr/2012/07/why-enum-singleton-are-better-in-java.html
http://javarevisited.blogspot.sg/2011/03/10-interview-questions-on-singleton.html
singleton pattern的推荐实现的更多相关文章
- 浅谈设计模式--单例模式(Singleton Pattern)
题外话:好久没写blog,做知识归纳整理了.本来设计模式就是个坑,各种文章也写烂了.不过,不是自己写的东西,缺少点知识的存在感.目前还没做到光看即能记住,得写.所以准备跳入设计模式这个大坑. 开篇先贡 ...
- .NET设计模式(2):单件模式(Singleton Pattern)(转载)
概述 Singleton模 式要求一个类有且仅有一个实例,并且提供了一个全局的访问点.这就提出了一个问题:如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?客户程 序在调用某一个类时,它是不 ...
- 单件模式(Singleton Pattern)(转)
概述 Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问点.这就提出了一个问题:如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?客户程序在调用某一个类时,它是不会考 ...
- .NET设计模式(2):单件模式(Singleton Pattern)
转载:http://terrylee.cnblogs.com/archive/2005/12/09/293509.html 单件模式(Singleton Pattern) --.NET设计模式系列之二 ...
- NET设计模式(2):单件模式(Singleton Pattern)[转载]
单件模式(Singleton Pattern) ——.NET设计模式系列之二 Terrylee,2005年12月07日 概述 Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问 ...
- .NET设计模式 第二部分 创建型模式(1)—:单件模式(Singleton Pattern)
单件模式(Singleton Pattern) ——.NET设计模式系列之二 Terrylee,2005年12月07日 概述 Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问 ...
- java23种设计模式之一: 单例模式(Singleton Pattern)
单例模式(Singleton Pattern)是设计模式中比较常用的一种,下面来总结单例模式的知识,包括: 1.理解什么是单例模式.单例模式有什么优点/缺点.单例模式的应用场景: 2.再来看看Java ...
- 十次艳遇单例设计模式(Singleton Pattern)
1.引言 单例设计模式(Singleton Pattern)是最简单且常见的设计模式之一,在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访 ...
- 设计模式01 创建型模式 - 单例模式(Singleton Pattern)
参考 [1] 设计模式之:创建型设计模式(6种) | 博客园 [2] 单例模式的八种写法比较 | 博客园 单例模式(Singleton Pattern) 确保一个类有且仅有一个实例,并且为客户提供一 ...
随机推荐
- CodeForces 548D 单调栈
Mike and Feet Time Limit:1000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Subm ...
- jQuery 选择同时包含两个class的元素的实现方法
Jquery选择器 多个 class属性参照以下案例 <element class="a b good list card"> 1. 交集选择: $(".a. ...
- sql 关于查询时 出现的 从数据类型 varchar 转换为 numeric 时出错 的解决方法。
出现这种问题 一般是查询时出现了 varchar 转 numeric 时出了错 或varchar字段运算造成的 解决方法: 让不能转的数不转换就可以了 sql的函数有个isNumeric(参数) 用 ...
- php集成动态口令认证
这篇文章主要为大家详细介绍了php集成动态口令认证,动态口令采用一次一密.用过密码作废的方式来提高安全性能,感兴趣的小伙伴们可以参考一下 大多数系统目前均使用的静态密码进行身份认证登录,但由于静态密码 ...
- c# Linq查询
c#提供的ling查询极大的遍历了集合的查询过程,且使用简单方便,非常的有用. 下面将分别用简单的例子说明:ling基本查询.延迟查询属性.类型筛选.复合from字句.多级排序.分组查询.联合查询.合 ...
- 教你一招:Win10系统如何正确卸载edge浏览器?
Edge浏览器作为Win10系统默认浏览器,尽管我们将其他浏览器设置为默认程序,但是有时候还是会自动弹出,非常的不爽,但是在控制面板中却又找不到卸载“Edge”浏览器的选项.下面小编就教大家卸载“Ed ...
- 解决: Sudamod/CM-13.0 源代码出现 Fatal: duplicate project .....问题
初始化代码库的时候出现如下错误: fatal: manifest ‘default.xml‘ not available fatal: duplicate project CyanogenMod/an ...
- 经典KMP算法C++与Java实现代码
前言: KMP算法是一种字符串匹配算法,由Knuth,Morris和Pratt同时发现(简称KMP算法).KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.比 ...
- zookeeper启动后没有相关进程
查看状态报错,报错,百度硕士nc问题,让看.out文件,但是这哥文件是空的,那就看log 016-12-15 14:08:19,355 [myid:] - INFO [main:QuorumPeer$ ...
- Python的方法解析顺序(MRO)[转]
本文转载自: http://hanjianwei.com/2013/07/25/python-mro/ 对于支持继承的编程语言来说,其方法(属性)可能定义在当前类,也可能来自于基类,所以在方法调用时就 ...