volatile,Interlocked:试图打破代码

Anr*_*nri 6 c# multithreading volatile thread-safety

首先,我试图找出使用Interlocked仍然需要volatile字段定义,这是我真正的问题.

但.懒得分析生成的MSIL我决定在实践中检查它.

我想为MSDN例如volatile使用时的代码应该在发布版本与优化打破.没有什么打破.代码工作正常(在这种情况下 - 主线程正常终止)开启和关闭优化.

  1. volatile当我从一个线程使用Interlocked并从另一个线程读取而没有锁定时,我是否仍然需要字段上的关键字?
  2. 一个问题的代码的简单例子哪里volatile有区别?
  3. 当我删除volatile关键字并在发布中构建时,为什么MSDN示例仍然有效?

用于说明问题1的代码段.

class Example
{
    volatile int val;

    void Do()
    {
        Task.Run(() => { while (val == 0) Console.WriteLine("running"); });

        Thread.Sleep(1000);
        Interlocked.Increment(ref val);
        Console.WriteLine("done.");
        Console.ReadLine();
    }
}
Run Code Online (Sandbox Code Playgroud)

Jim*_*hel 2

如果变量未标记为volatile,则读取它的代码无法知道它可能被其他线程修改。因此 JIT 编译器不会知道将值保存在寄存器中可能是不安全的。

volatile这就是告诉 JIT 编译器其他线程可以修改该值的方式。更改值时其他线程可能使用的内容Interlocked是无关紧要的,因为 JITer 甚至可能不知道其他代码存在!

您的简单示例可能有效,因为 JIT 编译器可以看到所有代码。如果这两段代码位于不同的方法甚至完全不同的程序集中,情况可能会大不相同。