Singlton implementation

  • Thread starter Thread starter DBC User
  • Start date Start date
D

DBC User

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();
}
}
}
}
 
DBC said:
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
 
Brian said:
The following article describes what's required in detail and offers
other suggestions as well.

http://www.yoda.arachsys.com/csharp/singleton.html

It is a very good article with some interesting
insight in both C# and .NET runtime.

But I do not like it if all programmer think
that they have to write one of the fancy solutions.

Unless one have special requirements the simple
solution is usually good enough and make it a lot
easier for people to read the code.

Arne
 
Arne Vajhøj said:
It is a very good article with some interesting
insight in both C# and .NET runtime.

But I do not like it if all programmer think
that they have to write one of the fancy solutions.

Unless one have special requirements the simple
solution is usually good enough and make it a lot
easier for people to read the code.

But interestingly, the solution you've just proposed is:

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

I think the following is simpler:

private static Singleton instance = new Singleton();
public static Singlton Instance
{
get
{
return instance;
}
}

That's just as lazy *unless* you call other static members on the type
before accessing the singleton, at which point I think we're into
"special requirements".
 
Jon said:
But interestingly, the solution you've just proposed is:

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

I think the following is simpler:

private static Singleton instance = new Singleton();
public static Singlton Instance
{
get
{
return instance;
}
}

That's just as lazy *unless* you call other static members on the type
before accessing the singleton, at which point I think we're into
"special requirements".

It is simpler and sufficient in most cases.

Which makes it good by definition in my book.

So I can follow your argument.

The only con I can see is that it is a bit different than GoF and C++
programmer will feel uncomfortable about it.

Arne
 
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
 
Arne said:
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

Arne,

It may work on x86 because that architecture has a relatively strong
memory model. But, remember, we don't code against x86, IA64, etc.
Instead we code against the CLR memory model which is weaker. So if it
works by accident then it's because the JIT compiler wasn't as
aggressive as the CLR specification allows in whatever version of the
framework was used. Change version of the framework and you may start
noticing problems.

I *think* double-checked locking does work in .NET if the volatile
keyword is used on the instance variable. At least that's what Vance
Morrison, et al. say.

Brian
 
| I *think* double-checked locking does work in .NET if the volatile
| keyword is used on the instance variable. At least that's what Vance
| Morrison, et al. say.

In his article, I think he said it does work in 2.0 without volatile, but
not ECMA.
http://msdn.microsoft.com/msdnmag/issues/05/10/MemoryModels/
http://www.bluebytesoftware.com/blog/PermaLink,guid,543d89ad-8d57-4a51-b7c9-a821e3992bf6.aspx
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/singletondespatt.asp
 
It may work on x86 because that architecture has a relatively strong
memory model. But, remember, we don't code against x86, IA64, etc.
Instead we code against the CLR memory model which is weaker. So if it
works by accident then it's because the JIT compiler wasn't as
aggressive as the CLR specification allows in whatever version of the
framework was used. Change version of the framework and you may start
noticing problems.

As I understand it the cause is at Intel not the JIT compiler
writer. Meaning that no framework upgrade will ever change it
on x86.

I may be wrong though. I am not a memory model expert. But that
is how I have read the writing about the topic.
I *think* double-checked locking does work in .NET if the volatile
keyword is used on the instance variable. At least that's what Vance
Morrison, et al. say.

True.

Arne
 
Arne Vajhøj said:
It is simpler and sufficient in most cases.

Which makes it good by definition in my book.

So I can follow your argument.

The only con I can see is that it is a bit different than GoF and C++
programmer will feel uncomfortable about it.

That just shows that the idiomatic way to implement a pattern (or even
how to tackle a problem) varies by language/platform - a very important
lesson.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top