c# - 与使用 Interlocked 类相比,使用 volatile 关键字有什么优势吗?

标签 c# .net multithreading volatile interlocked

换句话说,我可以用一个普通变量和 Interlocked 类也无法解决的 volatile 变量来做一些事情吗?

最佳答案

编辑:问题大部分重写

为了回答这个问题,我进一步深入研究了这个问题,发现了一些我不知道的关于 volatileInterlocked 的事情。让我们明确这一点,不仅是为了我,也是为了这次讨论和其他阅读此内容的人:

  • volatile 读/写应该不受重新排序的影响。此表示读写,表示任何其他 Action ;
  • volatility 不强制在 CPU 上,即硬件级别(x86 在任何读/写上使用获取和释放栅栏)。它确实会阻止编译器或 CLR 优化;
  • Interlocked 使用原子汇编指令进行 CompareExchange (cmpxchg)、Increment (inc) 等;
  • 互锁 有时会使用锁:hardware lock on multi processor systems ;在单处理器系统中,没有硬件锁;
  • Interlockedvolatile 的不同之处在于它使用全栅栏,而 volatile 使用半栅栏。
  • A read following a write can be reordered当你使用 volatile 时。 Interlocked 不会发生这种情况。 VolatileReadVolatileWrite 具有与 `volatile 相同的重新排序问题(链接感谢 Brian Gideon)。

现在我们有了规则,我们可以为您的问题定义一个答案:

  • 技术上:是的,有些事情可以用 volatile 做,而不能用 Interlocked 做:
    1. 语法:您不能写 a = b,其中 ab 是可变的,但这是显而易见的;
    2. 由于重新排序,您可以在将其写入 volatile 变量后读取不同的值。您不能使用 Interlocked 执行此操作。换句话说:使用 volatile 可以不太安全,然后可以使用 Interlocked
    3. 性能:volatileInterlocked 更快。​​
  • 语义上:不,因为 Interlocked 只是提供操作的超集并且使用起来更安全,因为它应用了完整的防护。你不能用 volatile 做任何你不能用 Interlocked 做的事情,你可以用 Interlocked很多你不能用 volatile 做的:

    static volatile int x = 0;
    x++;                        // non-atomic
    static int y = 0;
    Interlocked.Increment(y);   // atomic
    
  • 作用域:是的,声明一个变量 volatile 使其在每次访问时都可变。不可能以任何其他方式强制执行此行为,因此 volatile 不能替换为 Interlocked。在其他库、接口(interface)或硬件可以访问您的变量并随时更新它,或者需要最新版本的情况下,这是必需的。

如果你问我,这最后一点是对 volatile 的实际需求,并且可能使它成为两个进程共享内存并且需要在不锁定的情况下读取或写入的理想选择。在这种情况下,将变量声明为 volatile 比强制所有程序员使用 Interlocked(编译器无法强制执行)要安全得多。


编辑:以下引述是我原始答案的一部分,我将其保留在 ;-)

引自 C# 编程语言 标准:

For nonvolatile fields,optimization techniques that consider that reorder instructions can lead to unexpected and unpredictable results in multithreaded programs that access fields without synchronization such as that provided by the lock-statement. These optimizationscan be performed by the compiler, by the runtime system, or by hardware. For volatile fields, such reordering optimizations are restricted:

  • A read of a volatile field is called a volatile read. A volatile read has :acquire semantics"; that is, it is guaranteed to occur prior to any references to memory that occur after it in the instruction sequence.

  • A write of a volatile field is called a volatile write. A volatile write has "release semantics"; that is, it is guaranteed to happen after any memory references prior to the write instruction in the instruction sequence.

更新:问题已基本重写,更正了我的原始回复并添加了“真实”答案

关于c# - 与使用 Interlocked 类相比,使用 volatile 关键字有什么优势吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1701216/

相关文章:

jquery - 单击按钮时不显示 ajax 弹出窗口

java - 如何通过不断监听套接字来释放由Thread持有的互斥锁,该互斥锁永不松开

multithreading - 如何在不同处理器之间分配负载

c# - 判断集合是否相等(集合由集合组成)

.net - 基于 C#/ASP.NET 的网站中的 VB6 ActiveX 控件

c# - 无法从 Excel 列中读取字符串值

c# - 索引时查询 Solr 会导致索引中的文档丢失

Java Concurrent - 没有 speedUp 获得 LU 算法 - 虚假共享?

c# - 如何通过单击检查 CheckListBox 项目?

c# - 在一行 C# 中为公共(public)字节数组赋值