Henk,
Here are some problems:
1. Execution of the code in the same thread doesn't necessary means the
execution on the same processor.
2. Dotnet memory model guarantees that reads and writes from the same
processor to the *same memory location* would never cross each other,
but no guarantees about read/write to the different memory locations.
3. Even so bNeedInit assignment is atomic, but there is no guarantee
that that it will be visible to other processors in the same order as
preceding assignments during <init stuff>.

...
        lock(this) {
                <init stuff>
                bNeedInit = false;
                //<--your code is vulnerable right here
                // other processors could already see bNeedInit value is
false,          // but previous assignments during <init stuff> could
still be 
                // not available to the other processors.
                // memory barrier will be placed during exit from lock
block
                // on the next line.
        } // exits lock with all necessary memory barriers 

-Valery.

P.S. of course your code is guaranteed to work on X86 architecture due
to stronger memory model there.

-----Original Message-----
From: Henk de Koning [mailto:[EMAIL PROTECTED]] 
Sent: Monday, April 29, 2002 10:53 AM
To: [EMAIL PROTECTED]
Subject: Re: [DOTNET] lock - how expensive is it to call?

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.

Reply via email to