Hmm, I had been thinking of if (bNeedInit) { lock(this) { if (bNeedInit) { lock(this) { <init stuff> } bNeedInit = false; } } }
I agree with you that there was still a problem in the code I posted (although you must admit that it would safely initialize the value of variable bNeedInit ;-). About threads, sure they can hop across cpu's. However, the point was of course that while a thread is scheduled, it will run on one cpu only. Context switches surely don't alter the code sequence being executed ;-). I agree with you on your point that memory access from one cpu to one mem location is not reordered. That's the rule I was referring to. So, what can we learn from this: never post code from the top of your head and then respond to emails without rereading what you posted ;-);-). -- Henkk ----- Original Message ----- From: "Valery Pryamikov" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Sent: Monday, April 29, 2002 1:34 PM Subject: Re: [DOTNET] lock - how expensive is it to call? > BTW: > This kind of lazy init problem could be corrected following way: > > if (fNeedInit) { > lock (this) { > if (fNeedInitInt) { > <init stuff> > fNeedInitInt = false; > } > } //write barrier is performed by lock's release. > fNeedInit = false; > } > > Note: second if checks internal fNeedInitInt variable and fNeedInit is > updated outside of lock region. > (of course we consider that bNeedInit/fNeedInit/fNeedInitInt are not > volatile). > > -Valery. > > -----Original Message----- > From: Valery Pryamikov > Sent: Monday, April 29, 2002 11:55 AM > To: 'dotnet discussion' > Subject: RE: Re: [DOTNET] lock - how expensive is it to call? > > Henk, > Here are some problems: > 1. Execution of the code on the same thread doesn't necessaraly mean > execution of the code 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 it will be visible to other processors in the same order as > preceding assignments during <init stuff>. > > if (bNeedInit) { > lock(this) { > if (bNeedInit) { > <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; > > > } > > > > 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.