volatile关键字和Volatile.Read/Write有什么区别?

6

请问Volatile.ReadVolatile.Write对于非易失性整数的影响是否与正常读取和分配对于带有volatile修饰符的整数相同?

目的是为了防止出现警告,即不应该通过ref参数传递volatile变量到Interlocked方法中。(我知道尽管出现警告程序仍然正确,但我不想在我的代码中留下晦涩的预处理指令。)

//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);
}

同样地,我有一个DirectX渲染线程泵,它使用Interlocked.Exchange(ref command, null)消耗命令,一些命令使用易失性的直接赋值command变量产生。如果我安全地将其更改为Volatile.Write并删除volatile修饰符,是否会引入开销?
EDIT:明确的答案。今后,我将避免使用修饰符并始终通过Volatile和Interlocked明确地访问变量。这样代码就不会对访问类型存在歧义。修改变量声明也不会改变代码的含义。
在完美的世界中,我会使用编译器拒绝直接引用或分配变量的能力来使volatile修饰符有用。这将强制我通过Volatile或Interlocked或一个本身使用Volatile或Interlocked的方法传递引用。我应该找到Roslyn的副本。

下面线程中最受欢迎的答案说永远不要使用Volatile Read/Write。https://dev59.com/nmUp5IYBdhLWcg3wzp1k - Al Lelopath
@mickey,那是Thread.VolatileRead,而不是Volatile.Read。 - jnm2
1个回答

7
在您的情况下,没有任何区别;唯一的区别在于讨论单个数组元素时存在差异:
在C#中,使用volatile修饰符可以确保对字段的每次访问都使用Volatile.Read和Volatile.Write方法,但不能将volatile修饰符应用于数组元素。可以在数组元素上使用Volatile.Read和Volatile.Write方法。
因此,只要您绝对确定已捕获了涉及到的所有字段的用法,就可以安全地将总体的volatile更改为显式的volatile读/写。

4
我一直在想数组元素的不稳定性!太好了!以后,我会避免使用修饰符,并始终通过Volatile和Interlocked显式访问变量。这样就没有关于访问类型的歧义了。 - jnm2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接