Although I agree with you that there's more to synchronization in .Net than
meets the eye (is this correct English btw ?), I don't think there's a
problem with the code I posted. Here's why:

1) locks are internally implemented with volatile reads and writes (which
makes tons of sense ;-)
2) according to the CLR memory model, reads and writes from the same
processor will never cross each other
3) read/write reordening will never cross locks (they're implemented using
volatile)
4) all instructions in a sync'ed block of code will run on one thread and
hence on one processor

QED

-- Henkk

BTW, the problem you mention is very real and exactly the reason I forked
off the 'finding out if we need initialization' to a separate (valuetype)
variable.
BTW2, the C# volatile keyword is generally too rigid as it will cause *all*
reads and writes to the variable to be volatile
BTW3, bNeedInit is *not* a class with an implicit conversion operator for
bool ;-)

----- Original Message -----
From: "Ian Griffiths" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Sunday, April 28, 2002 12:24 AM
Subject: Re: [DOTNET] lock - how expensive is it to call?


> "Henk de Koning" wrote:
>
>
> >     if (bNeedInit) {
> >         lock(this) {
> >             if (bNeedInit) {
> >                 <init stuff>
> >                 bNeedInit = false;
> >             }
>
> This is the classic double check lock for lazy initialization strategy.
> Unfortunately, according to the strict definition of the .NET memory
model,
> this doesn't necessarily work - you can run into trouble due to the way
that
> the CLR allows multiprocessor caching architectures to reorder memory
> accesses.
>
> (It's broken under Java too for more or less exactly the same reasons by
the
> way.)
>
> See Vance Morrison's excellent essay on this subject here:
>
>  http://discuss.develop.com/archives/wa.exe?A2=ind0203B&L=DOTNET&P=R375
>
> and the correction he posted after he realised it had a typo here:
>
> http://discuss.develop.com/archives/wa.exe?A2=ind0203B&L=DOTNET&P=R25512
>
>
> In brief, you will actually get away with the above code on the current
CLRs
> because Pentiums are relatively conservative about how they order their
> memory accesses.  But there is the potential for it to be broken.  (Who
> knows how it will behave on a multi-processor IA64 system, for example?)
To
> fix it, you need to use a memory barrier operation.  Unfortunately the
> memory barrier operations aren't directly available in the current release
> of .NET - this article implies they will be in some future version.
> (However, I believe you can get the same effect as the
> System.Threading.Thread.MemoryBarrier(); by reading from and writing to a
> volatile variable.)
>
>
> --
> Ian Griffiths
> DevelopMentor
>
> You can read messages from the DOTNET archive, unsubscribe from DOTNET, or
> subscribe to other DevelopMentor lists at http://discuss.develop.com.
>

You can read messages from the DOTNET archive, unsubscribe from DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to