Singletons: Static ctors or Monitors?
-
In a recent thread on the ndoc development list (for which I contribute), we were talking about the documentation of static constructors and that got me to thinking: In most of my work, I use the approach for creating singleton objects by makeing a private constructor, then having a static property that returns an instance from which I can call other public or internal methods or properties. The whole thing looks like this:
public class Test
{
private string text;
private static Test instance;
private static volatile object syncRoot = new Object();
private Test()
{
this.text = "Test";
}
public static Test Instance
{
get
{
if (instance == null)
lock (syncRoot)
if (instance == null)
instance = new Test();
return instance;
}
}
public string Text
{
get { return this.text; }
}
}This seems to be the method that Microsoft uses in the .NET BCL. And it works good. I do use static constructors in some things that aren't so sensative (like wrapping some
GetDevice
Win32 API code). What I'm wondering is if static constructors work just as good as the method above? I haven't been able to find any documentation that discusses this in any detail, but my first reaction is that the first method is better because monitors are used and if would be thread-safe. But does the CLR invoke static constructors in a thread-safe manner on its own?Reminiscent of my younger years...
10 LOAD "SCISSORS" 20 RUN
-
In a recent thread on the ndoc development list (for which I contribute), we were talking about the documentation of static constructors and that got me to thinking: In most of my work, I use the approach for creating singleton objects by makeing a private constructor, then having a static property that returns an instance from which I can call other public or internal methods or properties. The whole thing looks like this:
public class Test
{
private string text;
private static Test instance;
private static volatile object syncRoot = new Object();
private Test()
{
this.text = "Test";
}
public static Test Instance
{
get
{
if (instance == null)
lock (syncRoot)
if (instance == null)
instance = new Test();
return instance;
}
}
public string Text
{
get { return this.text; }
}
}This seems to be the method that Microsoft uses in the .NET BCL. And it works good. I do use static constructors in some things that aren't so sensative (like wrapping some
GetDevice
Win32 API code). What I'm wondering is if static constructors work just as good as the method above? I haven't been able to find any documentation that discusses this in any detail, but my first reaction is that the first method is better because monitors are used and if would be thread-safe. But does the CLR invoke static constructors in a thread-safe manner on its own?Reminiscent of my younger years...
10 LOAD "SCISSORS" 20 RUN
acorrding to this article, the best way is thus:
// .NET Singleton sealed class Singleton { private Singleton() {} public static readonly Singleton Instance = new Singleton(); }
as for your threading question: "What about thread-safe initialization? The Framework addresses this too. The Framework internally guarantees thread safety on static type initialization." -
acorrding to this article, the best way is thus:
// .NET Singleton sealed class Singleton { private Singleton() {} public static readonly Singleton Instance = new Singleton(); }
as for your threading question: "What about thread-safe initialization? The Framework addresses this too. The Framework internally guarantees thread safety on static type initialization."Essentially, this is the same as using a static constructor. All statics that are initialized are done so in the
.cctor
specialname (the static constructor). Using the above syntax is merely a shorthand. So, you've actually described the same process. The first method I described and coded doesn't rely about a static constructor except for the synchronization object, which is only used by theMonitor
and is not indicative of the singleton itself. I appreciate your answer though. The latter part was good to know. I've always suspected based on evidence, but I've never been able to find it in the documentation which I've read from start to finish several times. (and, oh, how the ending makes me cry! :P)-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
-
Essentially, this is the same as using a static constructor. All statics that are initialized are done so in the
.cctor
specialname (the static constructor). Using the above syntax is merely a shorthand. So, you've actually described the same process. The first method I described and coded doesn't rely about a static constructor except for the synchronization object, which is only used by theMonitor
and is not indicative of the singleton itself. I appreciate your answer though. The latter part was good to know. I've always suspected based on evidence, but I've never been able to find it in the documentation which I've read from start to finish several times. (and, oh, how the ending makes me cry! :P)-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
Just remmeber static is only limited to its appdomain. leppie::AllocCPArticle(Generic DFA State Machine for .NET);