Thread-Safe Singleton

  • Thread starter Thread starter Robert Zurer
  • Start date Start date
R

Robert Zurer

I have a server application that makes a MarshalByReferenceObject available
via remoting. It's lifetime is set to never expire and it is implemented as
a Singleton.

Are calls to this object inherently thread safe? If 1000 threads all call
the same method of this object at once, do I have to add anything to my code
to assure that there are no problems?

Excuse me if this is really obvious. I am somewhat new to remoting and
totally new to multithreading.

Thanks in advance.


Robert Zurer
(e-mail address removed)
 
Robert,

This is a good question. If you have the object set up as a singleton,
then every call will come in to the same instance. Now if you have multiple
calls coming in to your object, then it is definitely possible that those
calls will come in on separate threads (if the calls are from seprate app
domains, or even different threads in the same app domain).

So, because of this, your object will have to handle the multithreaded
aspect. You should be placing sections of code in "lock" sections (or using
some other synchronization mechanism, but lock is the most common). For
more information on the lock keyword, check out the section of the .NET
framework documentation titled "lock Statement", located at (watch for line
wrap):

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vclrfLockStatement.asp

Hope this helps.
 
No, they aren't safe, inherently (though they might be by accident). The
reason is simple: you *may* be referencing resources (i.e. placing them in a
state that a single method call depends on) inside any one of your methods.
If you don't reference anything external in your method (i.e. only have
primative typed, by value input parameters and no local variables or field
references in your method) then your call is probably safe.

Richard
 
Jon Skeet has a superb article regarding this, you can find it at:
http://www.yoda.arachsys.com/csharp/singleton.html


Yes. I read it. I have a question though.

The code I have been using is this.


public sealed class Singleton
{

private Singleton(){}
public static readonly Singleton Instance = new Singleton();

}

This seems what Jon is referring to when he mentions a shortcut to the
fourth version of the Singleton pattern in his article. Am I right.

It's just not clear to me yet why this is thread-safe.
 
Robert Zurer said:
Yes. I read it. I have a question though.

The code I have been using is this.

public sealed class Singleton
{

private Singleton(){}
public static readonly Singleton Instance = new Singleton();

}

This seems what Jon is referring to when he mentions a shortcut to the
fourth version of the Singleton pattern in his article. Am I right.
Yes.

It's just not clear to me yet why this is thread-safe.

It's thread-safe in terms of *acquiring* the singleton - it doesn't
mean that methods within the type are automatically thread-safe. To be
honest, I don't know how/whether remoting affects this at all.
 
Jon Skeet said:
mean that methods within the type are automatically thread-safe. To be
honest, I don't know how/whether remoting affects this at all.


Thank you so much for responding. I have gained a tremendous amount from
your posts and your articles. They are incredible clear. Your baby is cute
too :-)

I do understand that methods of the singleton need to use locks if they
access a resource. I guess what I still don't understand is what is it
actuially, that makes the aquiring the instance thread-safe.

You say "static constructors in C# are specified to execute only when an
instance of the class is created or a static member is referenced, and to
execute only once per AppDomain"

In the abbreviated version, the static constructor is removed. Is the
static type initialization executed only once as well? Is that what
guarantees the thread-safety?


As regards remoting, I am not traversing AppDomains, but I am going to be
intercepting calls using ContextBoundObject. I access the Singleton from a
ServerContextSink. I don't know whether it would be safer to use the
implementation below.

private static Singleton Instance
{
get
{
if (instance == null)
lock (typeof(Singleton))
if (instance == null)
instance = new Singleton();
return instance;
}
}

Thanks again for all your help.


Robert Zurer
 
Robert Zurer said:
Thank you so much for responding. I have gained a tremendous amount from
your posts and your articles. They are incredible clear. Your baby is cute
too :-)
:)

I do understand that methods of the singleton need to use locks if they
access a resource. I guess what I still don't understand is what is it
actuially, that makes the aquiring the instance thread-safe.
Right.

You say "static constructors in C# are specified to execute only when an
instance of the class is created or a static member is referenced, and to
execute only once per AppDomain"

In the abbreviated version, the static constructor is removed. Is the
static type initialization executed only once as well? Is that what
guarantees the thread-safety?

Type initializers are guaranteed by the CLR specification to only be
executed once, and that anything else which would trigger type
initialization will wait until the type initializer has finished before
continuing. The difference the static constructor makes is only in
terms of exactly what triggers the initialization - you basically get
more guarantees about exact timing with it there, but the
initialization is safe either way.
As regards remoting, I am not traversing AppDomains, but I am going to be
intercepting calls using ContextBoundObject. I access the Singleton from a
ServerContextSink.

Unfortunately I know so little about remoting that I'm not much help
there - but I suspect you'll be fine with the normal methods.
I don't know whether it would be safer to use the
implementation below.

private static Singleton Instance
{
get
{
if (instance == null)
lock (typeof(Singleton))
if (instance == null)
instance = new Singleton();
return instance;
}
}

Definitely don't use the above - it's *not* threadsafe, IMO. It's
effectively the double-check lock algorithm, the third option on the
website.
 
hi Nicholas,

I got the same problem that Robert had. I have created a server-activated
singleton object on the server. I tried to call this object from a web
service coming from 2 different clients simultaneously but one remote object
call returns successfully while the other remote object call just hangs on
the browser. I use the lock(this) to lock the lengthy process (simulated by
Thread.Sleep(10000) on the server object).

How can I make both calls return successfully?

thanks
Joseph
Nicholas Paldino said:
Robert,

This is a good question. If you have the object set up as a singleton,
then every call will come in to the same instance. Now if you have multiple
calls coming in to your object, then it is definitely possible that those
calls will come in on separate threads (if the calls are from seprate app
domains, or even different threads in the same app domain).

So, because of this, your object will have to handle the multithreaded
aspect. You should be placing sections of code in "lock" sections (or using
some other synchronization mechanism, but lock is the most common). For
more information on the lock keyword, check out the section of the .NET
framework documentation titled "lock Statement", located at (watch for line
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vclrfLockStatement.asp

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Robert Zurer said:
I have a server application that makes a MarshalByReferenceObject available
via remoting. It's lifetime is set to never expire and it is implemented as
a Singleton.

Are calls to this object inherently thread safe? If 1000 threads all call
the same method of this object at once, do I have to add anything to my code
to assure that there are no problems?

Excuse me if this is really obvious. I am somewhat new to remoting and
totally new to multithreading.

Thanks in advance.


Robert Zurer
(e-mail address removed)
 
Back
Top