What is the difference between the volatile modifier and Volatile.Read/Write?

c#, multithreading

Solution

There is no difference in your scenario; the only difference exists when talking about individual array elements:

In C#, using the `volatile` modifier on a field guarantees that every access to that field uses the `Volatile.Read` and `Volatile.Write` methods, but the `volatile` modifier cannot be applied to array elements. The `Volatile.Read` and `Volatile.Write` methods can be used on array elements.

So, as long as you are absolutely sure that you have caught all usages of the fields in question, you can safely change the blanket `volatile` to explicit volatile reads/writes.

Problem

Do `Volatile.Read` and `Volatile.Write` have the exact same effect on a nonvolatile int that normal reads and assignments have on an int with the `volatile` modifier? The motivation is to prevent the warning that `volatile` variables should not be passed via ref parameters to the `Interlocked` methods. (I understand that the program is correct in spite of the warning, but I'd rather not leave enigmatic pragmas in my code.) ``` //private volatile int suppressListChangedEvents; private int suppressListChangedEvents; public void SuppressListChangedEvents() { Interlocked.Increment(ref suppressListChangedEvents); } public void UnsuppressListChangedEvents() { if (Interlocked.Decrement(ref suppressListChangedEvents) < 0) throw new InvalidOperationException("Too many calls to unsuppress."); } protected override void OnListChanged(ListChangedEventArgs e) { //if (suppressListChangedEvents != 0) return; if (Volatile.Read(ref suppressListChangedEvents) != 0) return; base.OnListChanged(e); } ``` Likewise, I have a DirectX render thread pump that consumes commands using `Interlocked.Exchange(ref command, null)` and some commands are produced using direct assignment to the volatile `command` variable. Can I safely change that to `Volatile.Write` and remove the `volatile` modifier without introducing overhead? EDIT: Definitive answer. Going forward, I'll shun the modifier and always explicitly access the variable via Volatile and Interlocked. That way the code has no ambiguity about the type of access; altering the variable declaration will not change the meaning of the code. In a perfect world, I would make the `volatile` modifier useful by having the compiler deny the ability to directly reference or assign to the variable. That would force me to pass the reference to Volatile or Interlocked or a method that would itself use Volatile or Interlocked. I should get my hands on a copy of Roslyn.

Original source

Related problems