volatile关键字用法

时间:2013-07-01 03:04:57

标签: c# volatile

我正在尝试理解volatile关键字的用法,所以我写了一个小例子,我在考虑使用Volatile关键字,但是目前我得到了相同的行为,要么我使用Volatile关键字,要么我不使用它

以下是我正在运行的代码,我期望Thread 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关键字的正确用法是什么,那将是很好的。

3 个答案:

答案 0 :(得分:3)

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

如果你没有告诉编译器这个变量是volatile,它可能会假设如果你把它设置为true然后在代码的某个时候使用它,那么这个变量仍然是真的并使用一些常量折叠逻辑优化代码。

答案 1 :(得分:1)

您是否已提及http://msdn.microsoft.com/en-us/library/x13ttww7(v=vs.71).aspx

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

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

您还可以参考c中提到的关于OS级别内部的以下线程Why is volatile needed in C?

答案 2 :(得分:1)

您没有观察到差异的原因是因为Console.WriteLine已经产生了一个内存障碍,使volatile在这个特定场景中变得多余。使用发布版本并在没有附加调试器的情况下运行应用程序来执行这些类型的测试也很关键。请查看我的答案herehere,但特别是here有关如何重现此问题的示例和解释。