There are a fair share of questions about Interlocked
vs. volatile
here on SO, I understand and know the concepts of volatile
(no re-ordering, always reading from memory, etc.) and I am aware of how Interlocked
works in that it performs an atomic operation.
But my question is this: Assume I have a field that is read from several threads, which is some reference type, say: public Object MyObject;
. I know that if I do a compare exchange on it, like this: Interlocked.CompareExchange(ref MyObject, newValue, oldValue)
that interlocked guarantees to only write newValue
to the memory location that ref MyObject
refers to, if ref MyObject
and oldValue
currently refer to the same object.
But what about reading? Does Interlocked
guarantee that any threads reading MyObject
after the CompareExchange
operation succeeded will instantly get the new value, or do I have to mark MyObject
as volatile
to ensure this?
The reason I'm wondering is that I've implemented a lock-free linked list which updates the "head" node inside itself constantly when you prepend an element to it, like this:
[System.Diagnostics.DebuggerDisplay("Length={Length}")]
public class LinkedList<T>
{
LList<T>.Cell head;
// ....
public void Prepend(T item)
{
LList<T>.Cell oldHead;
LList<T>.Cell newHead;
do
{
oldHead = head;
newHead = LList<T>.Cons(item, oldHead);
} while (!Object.ReferenceEquals(Interlocked.CompareExchange(ref head, newHead, oldHead), oldHead));
}
// ....
}
Now after Prepend
succeeds, are the threads reading head
guaranteed to get the latest version, even though it's not marked as volatile
?
I have been doing some empirical tests, and it seems to be working fine, and I have searched here on SO but not found a definitive answer (a bunch of different questions and comments/answer in them all say conflicting things).
Interlocked
operation will fail ifhead
got modified by another thread. The loop will spin around and try again. – Iodine