Thanks for all the info, good stuff. Interesting too, double-check lock in C# and all, CLI reference.
Ron -----Original Message----- From: Discussion of advanced .NET topics. [mailto:[EMAIL PROTECTED] On Behalf Of Greg Young Sent: Sunday, July 08, 2007 10:57 PM To: ADVANCED-DOTNET@DISCUSS.DEVELOP.COM Subject: Re: [ADVANCED-DOTNET] static variable, static property accessor Static constructors are gaurenteed in ECMA 335 to only be run once even in the case of multiple threads accessing the class for the first time concurrently. I quote from the spec. 10.5.3.1 Type initialization guarantees The CLI shall provide the following guarantees regarding type initialization (but see also §10.5.3.2 and §10.5.3.3): 1. As to when type initializers are executed is specified in Partition I. 2. A type initializer shall be executed exactly once for any given type, unless explicitly called by user code. 3. No methods other than those called directly or indirectly from the type initializer are able to access members of a type before its initializer completes execution. It is quite clearly stated that it will only be run once in item 2. If any CLR were to notdo this then it would be non-compliant to the spec. This only applies without beforefieldinit, with beforefieldinit the static constructor is called at the time that the type is loaded so its a moot point. Cheers, Greg On 7/8/07, J. Merrill <[EMAIL PROTECTED]> wrote: > I'm not questioning the accuracy of your statement, but I don't see a connection between "static constructors can only be called once" and "static constructors have an implicit lock." You seem to be saying that Ron Young's code will work but is doing more work than is necessary because of the "implicit lock" established by/for the static constructor. > > Surely it's possible to implement "only call the static constructor once" (e.g. with a two-state flag that gets tested and possibly set with an Interlocked call, and only calls the s.c. if the flag had not been set previously) without ensuring that the constructor will have completed execution before another thread (possibly on another processor) that uses the "run static constructor if not already run" facility (doing "test flag with Interlocked call / flag is set so don't (re-)run the static constructor") is able to access a not-yet-initialized value that will very shortly be set by the static constructor. > > Only if the 2nd thread that uses the "run static constructor if not yet run" facility is stalled until the static constructor is known to be complete (possibly by having 3 states for the flag, corresponding to "constructor not yet started", "constructor currently running", "constructor complete") is there safety without an explicit lock like Ron Young implemented. Your statement "static constructors have an implicit lock" suggests that you know that the CLR's implementation does something like that. Where did you get that information? > > Or am I misunderstanding your implication that Ron Young's code is doing more than is necessary? > > At 08:23 PM 7/8/2007, Peter Ritchie wrote > >Yes, it's thread-safe. Static constructors have an implicit lock (they > >can only be called once, so other threads must be locked out until the > >constructor is complete, should it currently be running). > > > >You've essentially implemented a singleton... > > > >-- Peter > > > >On Sun, 8 Jul 2007 18:00:19 -0500, Ron Young <[EMAIL PROTECTED]> > >wrote: > > > >>Say I have this class, I'm copying/pasting from Visual Studio: > >> > >> class StaticObject_VariableHolder > >> { > >> private static object _sharedVariable; > >> private static object _syncRoot = new object(); > >> > >> private StaticObject_VariableHolder() > >> { > >> } > >> > >> public static object SharedVariable > >> { > >> get > >> { > >> if (_sharedVariable == null) > >> { > >> lock (_syncRoot) > >> { > >> if (_sharedVariable == null) > >> { > >> _sharedVariable = new object(); > >> } > >> } > >> } > >> > >> return _sharedVariable; > >> } > >> } > >> } > >> > >>And I read this article, > >>http://msdn.microsoft.com/msdnmag/issues/05/08/Concurrency/ > >> > >>Is the following equivalent as above in regards to a one-time > >initialization > >>of a shared variable that is publicly (statically) accessible: > >> > >> > >> > >> /// <summary> > >> /// From http://msdn.microsoft.com/msdnmag/issues/05/08/Concurrency/ > >> /// on "What Memory Needs Lock Protection" > >> /// "Second; memory that is read-only after publication does not need > >a > >>lock > >> /// because any invariants associated with it must hold for the > >program > >> /// (since the value does not change). > >> /// </summary> > >> /// <typeparam name="T"></typeparam> > >> class BaseProvider<T> > >> { > >> private static readonly T _sharedObject; > >> > >> public static T SharedObject { get { return _sharedObject; } } > >> > >> static BaseProvider() > >> { > >> _sharedObject = default(T); > >> } > >> } > >> > >>It's not that we need BaseProvider to be singleton - although it could > >be - > >>but just access to it's shared variable. > > > J. Merrill / Analytical Software Corp > > =================================== > This list is hosted by DevelopMentor(r) http://www.develop.com > > View archives and manage your subscription(s) at http://discuss.develop.com > -- Studying for the Turing test =================================== This list is hosted by DevelopMentor® http://www.develop.com View archives and manage your subscription(s) at http://discuss.develop.com =================================== This list is hosted by DevelopMentor® http://www.develop.com View archives and manage your subscription(s) at http://discuss.develop.com