在C#中,关键字"volatile"的作用是什么?

6

我想看到Volatile关键字在C#中的实时使用,但我无法展示最好的例子。下面的样本代码在没有Volatile关键字的情况下工作,这怎么可能呢?

class Program
{
    private static int a = 0, b = 0;

    static void Main(string[] args)
    {
        Thread t1 = new Thread(Method1);
        Thread t2 = new Thread(Method2);

        t1.Start();
        t2.Start();

        Console.ReadLine();
    }

    static void Method1()
    {
        a = 5;
        b = 1;
    }

    static void Method2()
    {
        if (b == 1)
            Console.WriteLine(a);
    }
}

在上述代码中,我得到了一个值为5。没有使用volatile关键字它是如何工作的?

1
它不起作用。由于您忘记使用volatile,因此您期望获得除5之外的某些值。然而,您得到了5. 因此它 起作用,这正是您忘记某些内容时所预期的结果。(修复错误,神秘将从此消失。带有线程错误的代码几乎不可能理解。只需修复它们并忘记它。) - David Schwartz
你能给我举一个volatile的最佳例子吗? - Gun
现在,如果没有任何volatile关键字,就不能保证程序不会输出0。它可能(某一天)输出0。如果添加了volatile关键字,它就不能输出0,只能给出无输出或5的结果。 - Jeppe Stig Nielsen
如果您查看C#语言规范中的Volatile fields部分,有一个“最佳示例”与您自己的示例非常相似。 - Jeppe Stig Nielsen
2个回答

11

volatile关键字告诉编译器,变量可以在任何时候更改,因此不应优化变量的读写操作。

考虑这样的代码:

int sum;
for (var i = 0; i < 1000; i++) {
  sum += x * i;
}

由于循环内部变量x没有改变,编译器可能会在循环外部只读取一次变量值,然后在整个循环中都使用相同的值。

如果将变量x声明为易失性(volatile),编译器将在每次使用变量时都读取其值,因此如果您在另一个线程中更改了变量的值,则新值将立即生效。


2

如果您正确使用volatile,则可以保证代码正常工作。如果在需要使用volatile的代码中省略了它,大部分时间它可能会正常工作,但不能保证,并且当最需要时可能会失败。

要理解带有线程竞争的代码如何失败或不失败,需要对实现和平台有深入的了解。这不是简单的事情,通常不值得担心。只需遵循规则,您的代码将始终正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接