相关疑难解决方法(0)

C#中'volatile'关键字的目的是什么?

volatileC#中关键字的用途是什么?

我需要在哪里使用此关键字?

我看到以下声明,但我无法理解为什么volatile需要这里?

internal volatile string UserName; 
Run Code Online (Sandbox Code Playgroud)

c# multithreading volatile

17
推荐指数
3
解决办法
3809
查看次数

何时使用volatile来抵消C#中的编译器优化

我花了很多周时间在C#4.0中进行多线程编码.但是,有一个问题对我来说仍然没有答案.

我知道volatile关键字阻止编译器将变量存储在寄存器中,从而避免无意中读取过时值.写入在.Net中总是不稳定的,因此任何说明它也避免了stales写入的文档都是多余的.

我也知道编译器优化有些"不可预测".以下代码将说明由于编译器优化而导致的停顿(在VS之外运行发布编译时):

class Test
{
    public struct Data
    {
        public int _loop;
    }

    public static Data data;

    public static void Main()
    {
        data._loop = 1;
        Test test1 = new Test();

        new Thread(() =>
        {
            data._loop = 0;
        }
        ).Start();

        do
        {
            if (data._loop != 1)
            {
                break;
            }

            //Thread.Yield();
        } while (true);

        // will never terminate
    }
}
Run Code Online (Sandbox Code Playgroud)

代码表现如预期.但是,如果我取消注释//Thread.Yield(); 行,然后循环将退出.

此外,如果我在do循环之前放入Sleep语句,它将退出.我不明白.

当然,用volatile来装饰_loop也会导致循环退出(以其显示的模式).

我的问题是:编译器遵循的规则是什么,以确定何时隐含执行易失性读取?为什么我仍然可以通过我认为奇怪的措施退出循环?

编辑

IL代码如图所示(档位):

L_0038: ldsflda valuetype ConsoleApplication1.Test/Data ConsoleApplication1.Test::data
L_003d: ldfld int32 ConsoleApplication1.Test/Data::_loop
L_0042: ldc.i4.1 
L_0043: beq.s L_0038 …
Run Code Online (Sandbox Code Playgroud)

c# multithreading .net-4.0 compiler-optimization

15
推荐指数
1
解决办法
1158
查看次数