zoukankan      html  css  js  c++  java
  • async await 理解

    感谢这位大佬的讲解

    async await 异步,感觉是充分的利用了线程数。异步是指不是同一个线程的意思。

    作者:知乎用户
    链接:https://www.zhihu.com/question/439143561/answer/1678582955
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    异步方法和同步方法哪里不同呢?

    首先异步 != 多线程 , 这是两个层次的概念。多线程是实现异步的方式之一,单线程也一样可以实现异步。比如node.js。

    C#中更重要的是await,而不是async 。 async只是给编译器的提示标记。所以我们具体看看同步/异步函数内部的区别。

    public ActionResult PushFileData(FileData file){
        db.Save(file);
        Log("done");
    }
    
    public async Task<ActionResult> PushFileData(FileData file){
        await db.SaveAsync(file);
        Log("done");
    }
    

    同步:

    线程A开始执行代码,之后同步执行db.Save方法。 同步执行意味着,将数据发送到数据库,再到数返回写入成功,这一段时间,线程A是被阻塞的。也就是白白浪费了CPU的时间片。以及线程池中的一个线程对象。

    Save方法执行完之后仍然由线程A执行Log方法。

    异步:

    线程A开始执行代码,之后异步执行SaveAsync方法。 异步执行意味着,将数据发送并等待的这段时间,线程A被放回了线程池,换言之,没有占用任何线程。既然没有占用任何线程也就不存在占用CPU时间片。

    之后等到SaveAsync方法执行完毕后,又从线程池中获取一个线程(可能是A,也可能是其他线程),在执行Log方法。

    所以,上面的异步代码也等价于

    public Task<ActionResult> PushFileData(FileData file){
        return Task.Run(() => db.SaveAsync(file))
           .ContinueWith(lastTask => Log("done"));
    }
    //就和ES6的 .then()方法一样

    那么你可能又会问,你噼里啪啦说了这么多,同步方法和异步方法对于 CORE好像并没有什么用啊? 对于GUI程序起码还能让主界面不至于卡死。

    经过上面的一番分析之后,我们知道 CORE在执行控制器方法的时候同样依赖线程池。

    当有大量并发的请求时。比如10个吧,而你线程池的线程只有5个可用线程。

    那么你同步方法就会在同一时刻占用5个线程处理5个请求,剩下的5个请求就排队等待了。

    异步方法用于只执行本机的代码,不会阻塞等待网络IO,提前被放回线程池,那么原本剩下的5个请求就能被更快的处理啦。


    有了以上的认知我们来看一下题主的问题。

    疑问:对于同步方法,每个请求都是使用同个线程吗?如客户A请求同步Action,还未执行完毕时,客户B请求会阻塞。

    无论是同步方法还是异步方法,都会从线程池获取线程获取一个线程执行。

    所以,“ 使用同个线程?” ,答案是不一定。

    1. 如果线程A执行完被放回了线程池,下一次请求过来仍然获取的A线程,那么两次使用的是同一个线程。
    2. 如果线程A正在使用,则线程池中不存在A线程,可能获取的B线程,则是不同线程。
    3. 如果线程A执行完被放回了线程池,下一次请求过来获取的是B线程,则是不同线程。

    “还未执行完毕时,客户B请求会阻塞?”

    1. 如果线程池中还有剩余线程时,那么不会阻塞。
    2. 如果线程池中没有剩余线程时,那么会尝试创建一个新的线程。有两个阈值,一个是单位时间内创建的线程数,另一个是线程池中的总数。
    3. 如果没有到阈值,则创建线程。不会阻塞。
    4. 如果到达阈值,阻塞等待。

     

    对于异步方法,每个请求都是从线程池拿空闲线程出来执行方法?也就是客户A和客户B请求方法,都是在不同子线程里分别执行的
  • 相关阅读:
    Writing Custom Providers
    terraform 几个方便的工具
    几张简单的terraform flow 图——可以快速了解terraform的使用
    Stateful Kubernetes Applications Made Easier: PSO and FlashBlade
    使用k8s && minio 进行 postgres 数据库自动备份
    Understanding how uid and gid work in Docker containers
    nightwatchjs 基于nodejs&& webdriver 协议的自动化测试&&持续集成框架
    hasura graphql-engine graphql2chartjs 方便的graphql 转换chartjs 的类库
    nginx unit 1.8 支持基于java servlet 的开发模型
    试用 openresty/lua-resty-shell
  • 原文地址:https://www.cnblogs.com/elsons/p/15333146.html
Copyright © 2011-2022 走看看