Mixing `Volatile` with `Interlocked`
I believe this is safe to do so, but I'm asking this just in case.
Can you mix
Interlocked.CompareExchange
with Volatile.Write
like this?
I believe both would perform the atomic operations, so it should be safe to do so in this pattern.
Another question is whether the Interlocked.CompareExchange
synchronizes-with Volatile.Write
to create a happens-before relationship.
Which means, in C++ terms, if the Interlocked.CompareExchange
returns 0
, previous memory operations in /* Do some work here... */
should be also visible to the current thread.11 Replies
yes, it is fine to mix them like that
i am not sure what you mean by "if Interlocked.CompareExchange returns zero, the memory operations should be visible." if it returns zero, the memory operations haven't happened yet
you mean, if you call RefreshLobbies twice in a row?
Yes, for example two different threads calling
RefreshLobbies()
in a row
When both falls to the /* Do some work here... */
part, one of them should have happened first, so the result of the previous thread should be visible to the future threadthe compare exchange and volatile write ensures the memory operations do not fall outside of the lock
In other words, the thread that come next the first thread won't see the stale state before the first thread did something
all of the memory operations will complete before the flag is cleared
the volatile is a release, the interlocked is a full barrier. so nothing can move outside
yes, your lock looks fine
Yeah, looks like that's the case.
I was being pedantic because the msdn docs never mentions the memory ordering of
Interlocked
Thanks for the helpit is described in the memory model https://github.com/dotnet/runtime/blob/main/docs/design/specs/Memory-model.md
all of the interlocked methods are a full barier
Nice, thanks for clarifying
Piggybacking off of the question:
Does
int
require a volatile write operation here at all?
My understanding is that I would prefer volatile operations to prevent struct tearing, but int
is written atomically. Is this correct?the volatile is not about the atomicity
it is about the ordering of memory operations
the CPU and the compiler are allowed to execute memory reads and writes in a different order than the one which you wrote in the program
this code is implementing a lock. the write releases the lock. if the CPU or compiler chooses to take some of the code that yeon wrote “inside” of the lock and execute it after that release, you have a broken lock. someone could see the lock is released, and enter the lock, but the other thread is still editing the protected data structures
a Volatile write has “release semantics,” it means that any operations which were written before the write in the code must stay before the write. it is a useful property for… releasing a lock
That makes sense, thanks for the explanation!