Search code examples
c#volatilememory-barriers

Does a volatile write/read ensure visibility of "nearby" fields?


Just a simple example. No need to explain lock, Interlocked and so on.

The bool signals whether a value for state is available. state and the bool is not further modified afterwards.

int state;
volatile bool stateAvailable;

Thread A:
while(!stateAvailable) { sleep }
read state

Thread B:
state = 5;
stateAvailable = true;

Does this ensure that Thread A will always read the state correctly? I'm confused about the guarantees here (only for this simple example):

  • Will a volatile write ensure that operations before will have happened and the volatile read ensure that the operations after will not have happened, thereby also syncing processor state?
  • Or, will the volatile write/read only make sure that the compiler does not optimize away the bool-check from Thread A and it having no impact on the possibly stale value of state?

If you can point me to a duplicate of this question I'd be grateful as well.


Solution

  • No, nearby or not has nothing to do with it; you don't get any visibility or ordering guarantee just because a volatile class member or array element is in the same cache line.

    C# volatile accesses have acquire / release semantics.
    See volatile with release/acquire semantics for a quote from the C# standard.

    What makes your case safe is that the writer set stateAvailable = true; only after setting a value for the non-volatile "payload", and that the reader doesn't read the payload until after an acquire load sees the value from the writer's release-store.


    The MS documentation for C# volatile (https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes#1554-volatile-fields) includes a similar example with a volatile bool finished flag and a spin-wait.