Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Volatile vs Interlocked for reads and writes in C# [duplicate]

Possible Duplicate:
Volatile vs. Interlocked vs. lock

I am trying to understand situations when I would want to use the volatile keyword, vs Interlocked.

If I have a variable where every read from, and write to, that object is via Interlocked.Exchange, is that essentially the same thing as marking that variable as volatile?

private object _threadSafe;
private void Test()
{
    var tmp = new object();
    Interlocked.Exchange(ref tmp, _threadSafe); //read
    Interlocked.Exchange(ref _threadSafe, "hi"); //write

}

If, instead of this, the _threadSafe object was marked as volatile and I removed the Interlocked's, would that be functionally equivalent? (Assume I am not dependent on atomic read/increment/writes, like incrementing a value).

like image 834
user981225 Avatar asked Aug 31 '25 04:08

user981225


1 Answers

volatile guarantees that accesses are visible to other cores, as does Interlocked. The difference with interlocked is that it uses a full memory barrier for its guarantees and handles non-atomic operations. Volatile may not use a full memory barrier (depends on platform, e.g. x86/x64 don't need a full memory barrier with volatile...) but only makes atomic operations "thread-safe".

It's generally recommended to avoid volatile because it makes every atomic access to that variable "volatile" (which may not be that big a deal on x86/x64) and kinda hides the fact that access to the variable is different. Something like Interlocked is generally more recommended because it explicitly details the thread-safety concerns on each use of the variable.

Also, you can't use volatile on local variables, so if you wanted to use local variables with multiple threads, then Interlocked may be necessary. For example:

static void Main()
{
  bool complete = false; 
  var t = new Thread (() =>
  {
    bool toggle = false;
    while (!complete) toggle = !toggle;
  });
  t.Start();
  Thread.Sleep (1000);
  complete = true;
  t.Join();        // Blocks indefinitely
}

Update: To be clear, by "accesses" I mean already-atomic accesses. It should be blatantly obvious that just because a variable is "volatile" doesn't make every single operation on it thread-safe. That's not what I'm saying. e.g. on some platforms x++ is not thread-safe despite using volatile.

like image 154
Peter Ritchie Avatar answered Sep 02 '25 18:09

Peter Ritchie