The more interesting question in all of this is that even with completely safe code I cannot be assured by a conforming CLR that my object is actually ready to be used on my other thread.
"It is explicitly not a requirement that a conforming implementation of the CLI guarantee that all state updates performed within a constructor be uniformly visible before the constructor completes. CIL generators can ensure this requirement themselves by inserting appropriate calls to the memory barrier or volatile write instructions." On 7/9/07, Greg Young <[EMAIL PROTECTED]> wrote:
> It seems the controversial point is whether such out-of-order writes > can occur with the .NET 2.0 memory model. Vance Morrison has written > an article [1] where he seems to say no (in this case), so volatile > (or explicit memory barrier) are not needed. Other sources (such as > the MSDN articles cited) suggest to use volatile. Joe Duffy says > volatile is needed on some variants. In conversations I have been made aware of only one place where optimizations can occur and it is extremely obscure. In general the x86 JIT assumes every non-local to be volatile. the code in question ... public static object SharedVariable { get { if (_sharedVariable == null) { lock (_syncRoot) { if (_sharedVariable == null) { _sharedVariable = new object(); } } } return _sharedVariable; } } _sharedVariable = new object(); should only ever execute once providing the monitor does what it says that it does in the spec and performs a volatile write (and there is only a single write and not intermediary writes) as it also includes a reorderring gaurentee. I think this code is ok in any conforming memory model (the other dependency is stated in 12.6.6 that a reference size write is atomic). Cheers, Greg On 7/9/07, Fabian Schmied <[EMAIL PROTECTED]> wrote: > > This brings us to the interesting point, why is there disagreement? > > This is a very clear statement that monitor is indeed a superset of > > volatile. > > Yes, it is. But AFAIK, the problem is that the non-volatile read at > the beginning of Ron's code might see the assigned _provider member > before the constructor execution (or Activator.CreateInstance) has > finished execution (due to reordered writes). Yes, at the end of the > lock, it is as if the write had been volatile, but the non-volatile > read can see the assignment before the lock is released. > > This is also why volatile solves the problem - I understand that if > _provider is volatile, all out-of-order writes occur befor the > assignment is made. > > It is also why the explicit memory barrier suggested by Stoyan solves > the problem. Note that he does the following: > > I instance = Activator.... > Thread.MemoryBarrier(); // so that any out-of-order writes > complete[1] > provider_ = instance; > > So he ensures that all out-of-order writes finish before the > non-volatile read can see the result. > > It seems the controversial point is whether such out-of-order writes > can occur with the .NET 2.0 memory model. Vance Morrison has written > an article [1] where he seems to say no (in this case), so volatile > (or explicit memory barrier) are not needed. Other sources (such as > the MSDN articles cited) suggest to use volatile. Joe Duffy says > volatile is needed on some variants. > > Fabian > > [1] http://msdn.microsoft.com/msdnmag/issues/05/10/MemoryModels/ (Technique 4) > > =================================== > 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
-- 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