c# - volatile修饰符和Volatile.Read/Write有什么区别?

标签 c# multithreading

Volatile.ReadVolatile.Write对非 volatile int 的影响与正常读取和分配对具有 volatile 的 int 的影响完全相同修饰符?

这样做的目的是为了防止 volatile 变量不应通过 ref 参数传递给 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) 使用命令,并且一些命令是使用直接分配给 volatile command 变量。我可以安全地将其更改为 Volatile.Write 并删除 volatile 修饰符而不引入开销吗?

编辑:明确的答案。 展望 future ,我将避开修饰符,并始终通过 Volatile 和 Interlocked 显式访问变量。这样代码就不会对访问类型产生歧义;更改变量声明不会改变代码的含义。

在一个完美的世界中,我会让编译器拒绝直接引用或分配给变量的能力,从而使 volatile 修饰符变得有用。这将迫使我传递对 Volatile 或 Interlocked 的引用或本身使用 Volatile 或 Interlocked 的方法。我应该拿到一份 Roslyn。

最佳答案

你的场景没有区别;唯一的区别存在 when talking about individual array elements :

In C#, using the volatile modifier on a field guarantees that every access to that field uses the Volatile.Read and Volatile.Write methods, but the volatile modifier cannot be applied to array elements. The Volatile.Read and Volatile.Write methods can be used on array elements.

因此,只要您绝对确定您已经捕获了相关字段的所有用法,您就可以安全地将毯子 volatile 更改为显式 volatile 读取/写。

关于c# - volatile修饰符和Volatile.Read/Write有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24759947/

相关文章:

c# - 使用 VS 2010 创建的数据库部署网站

C# .net Protocol Buffer - protobuf-net 支持序列化对象值字典吗?

c# - Windows 8 CollectionViewSource ObservableCollection 绑定(bind)不更新

Python:如何阻止线程/多处理使用 100% 的 CPU?

java 并发 - 指令级并行(ILP)是否在底层使用

c# - 使用多个长时间运行的操作优化 ASMX Web 服务

c++ - 如何在 Poco 中设置在内核跟踪/ps/gdb 中调试可见的单个线程名称?

c# - 过滤列表并删除不需要的数据 C#

c# - 标签 TapGesture 不会触发 Xamarin Forms

multithreading - 哪个Linux系统调用用于获取线程的ID?