May as well toss more wood on. Here are two other methods. The first is
probably the easiest to remember, however it does require your singleton can
handle multiple instances for a short time (only 1 will ever be used
however). This method is can also be seen inside the framework. The second
method solves that issue by using a lock in the slow path. Neither method
takes a lock in the fast path.
public sealed class Singleton
{
private static Singleton instance;
private static readonly object syncRoot = new object();
private Singleton()
{
Console.WriteLine("Created Singleton.");
}
/// <summary>
/// This is a fast and easy to remember way to create a singleton.
However, your singleton *must be able to survive
/// multiple instances for a short time. Only 1 will every be "seen"
by user code however.
/// </summary>
/// <returns></returns>
public static Singleton Create1()
{
// This is a simple and fast double-checked locking pattern that
works. Also note instance does not
// need to be volatile. The Interlocked operation does not
block nor does it transition to kernel mode.
if (instance == null)
Interlocked.CompareExchange(ref instance, new Singleton(),
null);
return instance;
/*
* We could rewrite this as below to show why multiple
Singletons could be created.
* 1 or more threads could race passed the if test and each
would create another instance. Only the first
* we be used however and the other(s) will be collected. This
is why the singleton must be able to handle
* multiple instances for some time.
*
* if (instance == null )
* {
* Singleton s = new Singleton();
* Interlocked.CompareExchange(ref instance, s, null);
* }
* return instance;
*/
}
/// <summary>
/// This method is slightly more complex, but does guarantee only 1
instance will ever be created. The fast path is still a single "if" test
/// and takes no locks or Interlocked operations.
/// The lock is used for exclusive access to the block, not to
provide a memory barrier. The Interlocked.Exchange provides the
/// memory barrier and guarantees "instance" is always "seen"
correctly by other threads.
/// </summary>
/// <returns></returns>
public static Singleton Create2()
{
if (instance == null)
{
lock (syncRoot) // Exclusive lock to ensure we only create 1
instance of Singleton.
{
// Test again so that we don't run Interlocked again and
create another Singleton.
if (instance == null)
Interlocked.Exchange(ref instance, new Singleton());
}
}
return instance;
}
}
--
William Stacey [MVP]
| DBC User wrote:
| > Does any one know how to implment a singlton in c#. I have done the
| > implementation but I ran in to "Double-checked locking alert"
| > implemenation and not sure how to implement it. Or let me put it this
| > way, what is the equivalent of the following java code to resolve the
| > double-checked locking alert???
| >
| > private volatile static Singlton uniqueInstance
| >
| > public static Singlton getInstance()
| > {
| > if (uniqueInstance == null)
| > {
| > synchornized(Singlton.class) { <-- how can we do this in c#
| > if (uniqueInstance == null){
| > uniqueInstance = new Singlton();
| > }
| > }
| > }
| > }
|
| private static Singlton instance = null;
| private static object mylock = new object();
| public static Singlton Instance
| {
| get {
| lock(mylock)
| {
| if(instance == null)
| {
| instance = new Singlton();
| }
| }
| return instance;
| }
| }
|
| is what I would call the canonical form.
|
| NB: Double locking does not work properly in Java and last
| time I read the verdict was that it did not work in .NET
| either (just works accidentally on x86 platform).
|
| Arne