2

我试图了解 volatile 关键字的用法,所以我写了一个小例子,我想使用 Volatile 关键字,但目前我得到相同的行为,要么我使用 Volatile 关键字,要么我不使用它。

以下是我正在运行的代码,我希望线程 t2 继续执行,即使 t1 正在更新 ExitLoop 属性

namespace UsageOfVolatileKeyword
{
    class Program
    {
        static void Main()
        {
            Test t = new Test();

            Thread t2 = new Thread(() => { while (!t.ExitLoop) { Console.WriteLine("In loop"); } });
            t2.Start();

    Thread t1 = new Thread(() => t.ExitLoop = true);
            t1.Start();

            t2.Join();

            Console.WriteLine("I am done");

            Console.ReadLine();
        }
    }

    class Test
    {
        private bool _exitLoop = false; //I am marking this variable as volatile.

        public bool ExitLoop
        {
            get { return _exitLoop; }
            set { _exitLoop = value; }
        }
    }
}

如果有人能帮助我理解我做错了什么以及 Volatile 关键字的正确用法是什么,那就太好了。

4

3 回答 3

3

在高层次上,易失性是编译器“不对这个变量的状态做任何假设”的标志。本质上,您将使用它来指示多个线程或计算机本身的一部分可能正在更改此内存位置。例如,您可能会将某些内容映射到串行端口上的 UART 数据寄存器。当您读取此变量时,它的值是硬件中的任何值。

如果你不告诉编译器这个变量是 volatile 的,它可能会假设如果你将它设置为 true 然后在代码稍后的某个时刻使用它,这个变量仍然是 true 并使用一些常量折叠逻辑来优化代码。

于 2013-07-01T03:28:12.423 回答
1

您没有观察到差异的原因是因为Console.WriteLine已经生成了一个内存屏障,volatile在这种特定情况下会产生冗余。使用发布版本执行这些类型的测试并在没有附加调试器的情况下运行应用程序也很重要。在此处此处查看我的答案,尤其是此处,以获取有关如何重现此问题的示例和说明。

于 2013-07-12T15:25:44.900 回答
1

你有没有提到http://msdn.microsoft.com/en-us/library/x13ttww7(v=vs.71).aspx

volatile 提到的变量根据最近的 CPU 指令获得无缓存值,并且在编译期间没有编译器优化。

在您的情况下,我认为 CPU 有效地进行了上下文切换并且标志是一致的(有/无标志)。我想当有很多多线程并且cpu进行切换时我们可以看到一些不同

您还参考了以下线程Why is volatile in C? 在 c 中提到了关于操作系统级别内部的内容

于 2013-07-01T03:27:04.937 回答