Keywords: C#, Design Pattern, Singleton
The following code block is the most simple, however it is thread-safe. Refer to http://msdn2.microsoft.com/en-us/library/ms954629.aspx
// .NET Singleton
sealed class Singleton
{
private Singleton() {}
public static readonly Singleton Instance = new Singleton();
}
some more complex implemention are as follows,
/// <summary>
/// Class implements singleton pattern.
/// </summary>
public class Singleton
{
// Private constructor to avoid other instantiation
// This must be present otherwise the compiler provide
// a default public constructor
private Singleton()
{
}
/// <summary>
/// Return an instance of <see cref="Singleton"/>
/// </summary>
public static Singleton Instance
{
get
{
/// An instance of Singleton wont be created until the very first
/// call to the sealed class. This a CLR optimization that ensure that
/// we have properly lazy-loading singleton.
return SingletonCreator.CreatorInstance;
}
}
/// <summary>
/// Sealed class to avoid any heritage from this helper class
/// </summary>
private sealed class SingletonCreator
{
// Retrieve a single instance of a Singleton
private static readonly Singleton _instance = new Singleton();
/// <summary>
/// Return an instance of the class <see cref="Singleton"/>
/// </summary>
public static Singleton CreatorInstance
{
get { return _instance; }
}
}
}
上面的代码没有考虑singleton对象的线程安全问题. 在用VS2005向导生成Settings类和Resource类的时候, 你会注意到Setting类需要考虑线程同步问题, 因为程序可能不仅仅会读取外部的config文件, 也有可能会修改config文件的信息. 而Resource类不需要考虑线程同步的问题, 因为一般程序不会修改Resource.res的文件.
那么怎样为singleton类增加线程同步问题呢? 查看Settings.Designer.cs文件, 会发现在创建defaultInstance时候, 用了下面的代码:
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
通过Reflector工具, 可以看到ApplicationSettingsBase.Synchronized()方法是个static方法, 传入的参数就是一个Settings类的实体, 这个方法仅仅是将settings对象的 IsSynchronized属性设置为True, 再看一下ApplicationSettingsBase类的Save()方法, 读取的方法和Save()方法类似. 就明白它是怎样完成线程同步的.
//ApplicationSettingsBase class
public virtual void Save()
{
if (this.IsSynchronized)
{
lock (this)
{
this.SaveCore();
return;
}
}
this.SaveCore();
}
No comments:
Post a Comment