views:

419

answers:

5

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?

+1  A: 

Yes - you can look at the value directly.

As long as you ONLY use the Interlocked class to access the variable then there is no difference. What volatile does is it tells the compiler that the variable is special and when optimizing it shouldn't assume that the value hasn't changed.

Takes this loop:

bool done = false;

...

while(!done)
{
... do stuff which the compiler can prove doesn't touch done...
}

If you set done to true in another thread you would expect the loop to exit. However - if done is not marked as volatile then the compiler has the option to realize that the loop code can never change done and it can optimize out the compare for exit.

This is one of the difficult things about multithread programming - many of the situations which are problems only come up in certain situations.

Aaron
You can do the same with Interlocked.Read().
codymanix
Your description of volatile is slightly wrong. You describe c++ volatile (no good for multithreading). C# (and Java) volatile make the compiler insert sync operations when accessing the variable. Because of the syncs, it is forced to reread the variable everytime, which has an effect similar to c++'s volatile.
caspin
+7  A: 
Abel
The Interlocked class doesn't have to do much with a lock and it has (in contrast to lock) not much overhead assigned with it - on most CPUs the Interlocked methods are implemented as single instruction.
codymanix
You are correct, thanks for pointing at it. Looking into `CompareExchange` (thinking it wouldn't be atomic) SSCLI (shared source CLI) shows that it ultimately translates to the `cmpxchg` assembly instruction on x86 processors, and that instruction is — as anything else in `Interlocked` — indeed atomic.
Abel
That, and other corrections, plus rewrite are now in the answer :)
Abel
You siad, you cannot enforce threadsafe access to a variable without the volatile keyword. But you can define a property which uses Interlocked.Read() and Interlocked.Exchange() in its getter/setter.
codymanix
That's disguising a variable. Of course you can do that. But it doesn't change the fact that you can't have a *variable* or a *field* that way. Hidden behind a property makes the field less prone to error, but inside the class and from outside (breaking OO through reflection), it's just accessible, with thread-unsafety and all. OTOH, it isn't possible to give the address of a "volatiled" property to some external function (API, hardware, otherwise), you need to hand in the address of the field and no way Interlocked can help then.
Abel
Passing a reference of a volatile variables is loosing it's volatility, the compiler will warn you if you try it. However, your answer is very good and exhausting :)
codymanix
Agreed, but isn't that a warning about the *reference*, which means that reading/writing the variable still has the same semantics? Otherwise, how would the CLR allow using `volatile` for variables that can be written to by other libs or even hardware?
Abel
A: 

This is fairly complex topic. I find Joseph Albahari's writeup to be one of the more definitive and accurate sources for multithreading concepts in the .NET Framework that might help answer your question.

But, to quickly summarizes there is a lot of overlap between the volatile keyword and the Interlocked class as far as how they can be used. And of course both go way above and beyond what you can do with a normal variable.

Brian Gideon
Very great article! It will take a while to read it and a much longer while to fully understand it
codymanix
A: 

I won't attempt to be an authority on this subject but I would highly recommend that you take a look at this article by the vaunted Jon Skeet.

Also take a look at the final part of this answer which details what volatile should be used for.

akmad
Skeet's article is good but just coveres the basics. I know what volatile is good for, but the question was if there is any situation where you can't replace volatile with an interlocked method?
codymanix
A: 

Yes, you can gain some performance by using a volatile variable instead of a lock.

Lock is a full memory barrier which can give you the same characteristics of a volatile variable as well as many others. As has already been said volatile just ensures that in multi-threaded scenarios if a CPU changes a value in its cache line, the other CPUs sees the value immediately but do not ensure any locking semantic at all.

The thing is lock is a lot more powerful than volatile and you should use volatile when you can to avoid unnecessary locks.

Jorge Córdoba
I wasn't talking about the lock statement, but the Interlocked class, but yes what you said is true
codymanix