Re: When is "volatile" used instead of "lock" ?

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



"Jon Skeet [C# MVP]" <skeet@xxxxxxxxx> wrote in message news:MPG.20db8fad270511ef21e@xxxxxxxxxxxxxxxxxxxxxxx
Peter Ritchie [C# MVP] <PRSoCo@xxxxxxxxxxxxxxxxx> wrote:

<snip>

By the same token, the lock statement surrounding access to a member doesn't
stop the compiler from having optimized use of a member by caching it to a
register especially if that member is declared in a different assembly that
was compiled for this code was written:

lock(lockObject)
{
i = i + 1;
}

Acquiring a lock has acquire semantics, and releasing a lock has
release semantics. You don't need any volatility if all access to any
particular item of shared data is always made having acquired a certain
lock.

If different locks are used, you could be in trouble, but if you always
lock on the same reference (when accessing the same shared data) you're
guaranteed to be okay.

...yes, the compiler *could* assume that all members within the lock
statement block are likely accessible by multiple threads (implicit
volatile); but that's not its intention and it's certainly not documented as
doing that (and it would be pointless, other code knows nothing about this
block and could have optimized use of i by changing its order of access or
caching to a registry).

It certainly *is* documented. ECMA 335, section 12.6.5:

<quote>
Acquiring a lock (System.Threading.Monitor.Enter or entering a
synchronized method) shall implicitly
perform a volatile read operation, and releasing a lock
(System.Threading.Monitor.Exit or leaving a
synchronized method) shall implicitly perform a volatile write
operation.
</quote>

volatile and lock should be used in conjunction, one is not a replacement
for the other.

If you lock appropriately, you never need to use volatile.



True, when using locks, make sure you do it consistently. And that's exactly why I said that I'm getting suspicious when I see a "volatile" field. Most of the time this modifier is used because the author doesn't understand the semantics of "volatile", or he's not sure about his own locking policy or he has no locking policy at all. Also some may think that volatile implies a fence, which is not the case, it only tells the JIT to turn off some of the optimizations like register allocation and load/store reordering, but it doesn't prevent possible re-ordering and write buffering done by the CPU, note, that this is a non issue on X86 and X64 like CPU's , given the memory model enforced by the CLR, but it is an issue on IA64.

Willy.

.



Relevant Pages

  • RE: When is "volatile" used instead of "lock" ?
    ... register especially if that member is declared in a different assembly that ... Acquiring a lock has acquire semantics, ... volatile); but that's not its intention and it's certainly not documented as ... caching to a registry). ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Threadsafe value types
    ... This is a good point but the use of a lock does not actually eliminate the ... compiler or runtime from optimizations on fields not marked as volatile. ... >> optimizations that cause caching and hence problems regardless of the use ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: When is "volatile" used instead of "lock" ?
    ... I've been trying to get to your assertion of no JIT optimizations of members ... between Enter/Exit because of "volatility guarantees" in the CLI spec. ... between Enter/Exit were considered volatile operations-which is probably why ... publicly visible object is used as the lock object, ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: [OT] volatile in userspace
    ... Without 'volatile' and disabling optimizations altogether, ... 'Compiler over-optimisations and "volatile"'), volatile is used to ... Well, if you look at the Wiki, it admits that this is a bug: ...
    (Linux-Kernel)
  • Re: [PATCH 0/24] make atomic_read() behave consistently across all architectures
    ... It doesn't mean that (volatile int*) cast is bad, ... I would agree that fixing the compiler in this case would be a good thing, ... bad register allocation. ... still quite possible to find cases where it did some optimization (in this ...
    (Linux-Kernel)