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

===================================
This list is hosted by DevelopMentorĀ®  http://www.develop.com

View archives and manage your subscription(s) at http://discuss.develop.com

Reply via email to