异步/等待线程安全与内存缓存

apr*_*ate 6 .net c# multithreading caching asynchronous

我正在查看http://www.albahari.com/threading/part4.aspx中描述的有关内存屏障的部分, 并试图制作"我们真的需要锁定和"下提供的示例的异步/等待版本壁垒"?

public class Program
{
    static void Main(string[] args)
    {
        TestAsync();
        Console.ReadKey(true);
    }

    private static async void TestAsync()
    {
        bool complete = false;
        Func<Task> testFunc = async () =>
        {
            await Task.Delay(1000);
            bool toggle = false;
            while (!complete) toggle = !toggle;
        };

        var task = testFunc();
        Thread.Sleep(2000);
        complete = true;
        await task;
        Console.WriteLine("Done");
    }
}
Run Code Online (Sandbox Code Playgroud)

在没有调试的情况下在释放模式下运行时,程序将永远不会按照它所基于的原始线程示例完成.

但是,由于上下文保存的方式,我在async/await的印象下会阻止这些问题.或者在使用async/await时是否仍然适用所有线程安全规则?

Mic*_* II 7

这实际上是一个编译优化问题.当您在发布中编译时出于某种原因,它预测完成将永远不会是真的并无限运行您的应用程序.既然你是基于另一个例子,我猜你已经知道了.但就async/await而言,它不能归咎于它.

要完成这项工作,您仍然需要将complete设置为volatile变量,如下所示:

        static volatile bool complete = false;
Run Code Online (Sandbox Code Playgroud)

这将告诉编译器每个周期检查它,无论它是否有效.

我不是说我同意它,但正在发生的事情是编译器看到完全没有变化直到while(!complete)部分,并且因为没有volatile关键字它决定它永远不会改变为优化性能.

另一种使这项工作的方法是删除编译器优化.您可以单击项目"属性",然后单击"构建"选项卡,并取消选中"优化代码".然后它将在发布中工作.