Is there any advantage of using volatile keyword in contrast to use the Interlocked class?
.net, c#, interlocked, multithreading, volatile
Solution
EDIT: question largely rewritten
To answer this question, I dived a bit further in the matter and found out a few things about `volatile` and `Interlocked` that I wasn't aware of. Let's clear that out, not only for me, but for this discussion and other people reading up on this:
- `volatile` read/write are supposed to be immune to reordering. This only means reading and writing, it does not mean any other action;
- volatility is not forced on the CPU, i.e., hardware level (x86 uses acquire and release fences on any read/write). It does prevent compiler or CLR optimizations;
- `Interlocked` uses atomic assembly instructions for CompareExchange (`cmpxchg`), Increment (`inc`) etc;
- `Interlocked` does use a lock sometimes: a hardware lock on multi processor systems; in uni-processor systems, there is no hardware lock;
- `Interlocked` is different from `volatile` in that it uses a full fence, where volatile uses a half fence.
- A read following a write can be reordered when you use `volatile`. It can't happen with `Interlocked`. `VolatileRead` and `VolatileWrite` have the same reordering issue as `volatile (link thanks to Brian Gideon).
Now that we have the rules, we can define an answer to your question:
- Technically: yes, there are things you can do with `volatile` that you cannot do with `Interlocked`:
- Syntax: you cannot write `a = b` where `a` or `b` is volatile, but this is obvious;
- You can read a different value after you write it to a volatile variable because of reordering. You cannot do this with `Interlocked`. In other words: you can be less safe with `volatile` then you can be with `Interlocked`.
- Performance: `volatile` is faster then `Interlocked`.
Semantically: no, because `Interlocked` simply provides a superset of operations and is safer to use because it applies full fencing. You can't do anything with `volatile` that you cannot do with `Interlocked` and you can do a lot with `Interlocked` that you cannot do with volatile:
static volatile int x = 0;
x++; // non-atomic
static int y = 0;
Interlocked.Increment(y); // atomic
Scope: yes, declaring a variable `volatile` makes it volatile for every single access. It is impossible to force this behavior any other way, hence `volatile` cannot be replaced with `Interlocked`. This is needed in scenarios where other libraries, interfaces or hardware can access your variable and update it anytime, or need the most recent version.
If you'd ask me, this last bit is the actual real need for `volatile` and may make it ideal where two processes share memory and need to read or write without locking. Declaring a variable as `volatile` is much safer in this context then forcing all programmers to use `Interlocked` (which you cannot force by the compiler).
EDIT: The following quote was part of my original answer, I'll leave it in ;-)
A quote from the the C# Programming Language standard:
For nonvolatile fields,optimization techniques that consider that reorder instructions can lead to unexpected and unpredictable results in multithreaded programs that access fields without synchronization such as that provided by the lock-statement. These optimizationscan be performed by the compiler, by the runtime system, or by hardware. For volatile fields, such reordering optimizations are restricted:
A read of a volatile field is called a volatile read. A volatile read has :acquire semantics"; that is, it is guaranteed to occur prior to any references to memory that occur after it in the instruction sequence.
A write of a volatile field is called a volatile write. A volatile write has "release semantics"; that is, it is guaranteed to happen after any memory references prior to the write instruction in the instruction sequence.
Update: question largely rewritten, corrected my original response and added a "real" answer
Problem
In other words, can I do something with a volatile variable that could not also be solved with a normal variable and the Interlocked class?