具有内存缓存的异步/等待线程安全 [英] Thread safety on async/await with memory caching

查看:47
本文介绍了具有内存缓存的异步/等待线程安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was having a look at the section on memory barriers as described in http://www.albahari.com/threading/part4.aspx and attempted to make an async/await version of the example provided under 'Do We Really Need Locks and Barriers?':

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");
    }
}

在发布模式下运行且未经调试的情况下,该程序将永远无法根据其基于的原始线程示例完成操作.

When run under release mode without debugging, the program will never finish as per the original threading example it's based off.

但是,由于上下文的保存方式,它可以防止此类问题,因此我对async/await印象深刻.还是在使用异步/等待时所有线程安全规则仍然适用?

However, I was under the impression with async/await because of the way the context is saved it would prevent these kinds of issues. Or do all thread safety rules still apply when using async/await?

推荐答案

这实际上是编译优化问题.当您出于某种原因在发行版中进行编译时,它会预测complete永远不会是正确的,并且会无限期地运行您的应用程序.由于您已经基于另一个示例,所以我想您已经知道了.但是就异步/等待而言,这不能被指责.

This is actually a compile optimization issue. When you compile in release for some reason it predicts complete will never be true and infinitely runs your application. Since you've based this on another example I'm guessing you already knew that. But as far as the async / await it can't be blamed.

要完成这项工作,您仍然需要像complete这样将其设置为易失变量:

To make this work you would still need to set complete as a volatile variable like so:

        static volatile bool complete = false;

这将告诉编译器在每个周期都对其进行检查,并且它将起作用.

This will tell the compiler to check it every cycle regardless and it will work.

我并不是说我同意这一点,但是正在发生的是编译器一直看到完全不变,直到while(!complete)节,由于没有volatile关键字,它决定永远不会这样做.进行更改以优化性能.

I'm not saying I agree with it but what's happening is the compiler is seeing complete unchanged all the way up to the point of the while(!complete) section and since there is no volatile keyword it decides it's never going to change to optimize performance.

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

Another way to make this work is to remove the compiler optimizations. You can click on the project Properties and then the Build tab and uncheck 'Optimize code'. Then it will work in release.

这篇关于具有内存缓存的异步/等待线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆