在 SO 上有很多关于Interlockedvs. volatilehere 的问题,我理解并知道volatile(不重新排序,总是从内存中读取等)的概念,并且我知道Interlocked它是如何执行原子操作的。
但我的问题是这样的:假设我有一个从多个线程读取的字段,它是某种引用类型,比如说:public Object MyObject;。我知道,如果我对它进行比较交换,如下所示:Interlocked.CompareExchange(ref MyObject, newValue, oldValue)互锁保证只写入引用newValue的内存位置ref MyObject,如果ref MyObject和oldValue当前引用同一个对象。
但是阅读呢?是否Interlocked保证操作成功MyObject后读取的任何线程CompareExchange都会立即获得新值,还是我必须标记MyObject为volatile确保这一点?
我想知道的原因是我已经实现了一个无锁链表,当你向它添加一个元素时,它会不断更新自身内部的“头”节点,如下所示:
[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));
}
// ....
}
现在Prepend成功后,是否保证读取的线程head获得最新版本,即使它没有标记为volatile?
我一直在做一些实证测试,它似乎工作正常,我在这里搜索过但没有找到明确的答案(一堆不同的问题和评论/答案都说相互矛盾的事情)。