扫一扫,手机访问
15194118449

做网站为什么要用async

发表日期:2020-08-19 16:28 文章编辑:John0King 浏览次数:78
本站原创,转载请注明出处和网址

 

为什么要用async

答案很简单:提供程序的吞吐量, 通过提供CPU的使用率,充分的利用机器的性能,实现高并发。

异步的使用


    /// 读取文件所有的字节
  public async Task<byte[]> ReadFile()
    {
        using (var ms = new MemoryStream())
        {
            using (var fileStream = File.Open(@"D:/a.txt", FileMode.Open))
            {

                await fileStream.CopyToAsync(ms);
            }

            return ms.ToArray();
        }

    }

 

容易混淆的概念

 

async 和 parallel 是比较容易让人们混淆的两个概念, async 也叫异步, parallel 也叫 并行, 他们都是一种多线程技术,这也是造成 人们混淆的主要原因。

 

什么是 Parallel

 

parallel 是并行,是一种CPU使用率换时间的场景,也是人们对多线程最“直观” 的理解, 执行过程请看下图

 

并行CPU执行图

 

该模式适合 单“用户” 多任务的场景, 举个例子, 现在有4个包裹要分别投递到东南西北四个客户手里, 与其让1个人送, 不如让 4个人同时送, 这样 对于“快递公司” 这个“用户而言”, 相比1个人送,节省了很大的时间

 

什么是 Async

 

async 也叫异步,也是一种多线程技术,相比与 parallel 跟不容易被人们锁理解。 异步 是一种 CPU使用率换吞吐量的场景。

 

这里来个案例, 先抛出一个问题:

 

现在公司有4个工人,然而现在有20项工作, 假如这项工作是种树,他有以下几个步骤, 1) 刨坑, [时间=2] 2) 等待运输公司的工人把树运来[时间=6] 3) 把树放到坑里,并埋上土 [时间=2] 4) 去申请用水,等待审批 [时间=6] 5) 浇水[时间=2]
这里请忽略里面的不合理之处,一项任务的完成,必须按顺序完成上述的5个步骤

 

如果是同步+ paralle 的方式, 一次可以同时开始4个工作, 单每个工作都需要 2 + 6 + 2 + 6 + 2 = 18 个时间单位, 总共完成需要 18 * 20 / 4 = 90 个时间单位。

 

让我们来用异步看一下: 首先4个工人同时刨坑, 完成后,不是等着送树过来, 而是开始 另外一个工作, 也就是再次刨坑 , 因为还没有送过来, 再开始另外4项工作,完成后, 终于第开始的树送过来了,然后埋土, 然后申请用水, 这里不等着审批, 而是把第二次送来的树放到坑里,埋土, 然后申请,不等审批, 然后把第3次的树载上,然后申请水, 这时候,申请通过,浇水, 第一次的4个工作被完成了。以此往复 。。。。, 让我们看看时间的使用情况

 

t01 -> 2
t02 -> 2
t03 -> 2
t04 -> 2
    t05 -> 2
    t06 -> 2
    t07 -> 2
    t08 -> 2
        t09 -> 2
        t10 -> 2
        t11 -> 2
        t12 -> 2 
            t01 -> 6 -> 2
            t02 -> 6 -> 2
            t03 -> 6 -> 2
            t04 -> 6 -> 2
                t05 -> 6 -> 2
                t06 -> 6 -> 2
                t07 -> 6 -> 2
                t08 -> 6 -> 2
                    t09 -> 6 -> 2
                    t10 -> 6 -> 2
                    t11 -> 6 -> 2
                    t12 -> 6 -> 2
                        t13 -> 2
                        t14 -> 2
                        t15 -> 2
                        t16 -> 2
                            t17 -> 2
                            t18 -> 2
                            t19 -> 2
                            t20 -> 2
                                空闲,抽根烟
                                空闲,抽根烟
                                空闲,抽根烟
                                空闲,抽根烟
                                    t13 -> 6 -> 2
                                    t14 -> 6 -> 2
                                    t15 -> 6 -> 2
                                    t16 -> 6 -> 2
                                        t17 -> 6 -> 2
                                        t18 -> 6 -> 2
                                        t19 -> 6 -> 2
                                        t20 -> 6 -> 2

从时间上看,每个任务从开始到结束 每个都是 18个时间单位, 但是总完成却只用了 24 个时间单位, 这是因为步骤三 长达 6 个时间单位的等待, 让这 4个工人,几乎同时开始了12 个工作, 这也就是我们所说的吞吐量。(ps, CPU 开始新工作的时候会耗费一丢丢的时候, 在这个例子里, 每个任务从开始到结束要比 18 个时间单位长一丢丢, 比如 每个任务要用时 18.2 个时间单位,我们在上面的计算中忽略了部分, 也就是 异步相比同步每个任务上要多用一丢丢的时间, 但带来极大的吞吐量)

 

下面是CPU执行示意图 

异步CPU执行示意图

 

需要注意的是:上面举的例子中, 送树的人 和 用水审批的人,就是“外部工作者”, 所以一个真正的异步,必然涉及2个线程。 在web领域上,比如访问数据库,访问外部的api 等,他们都是异步的,大家都知道 TCP 的处理是在操作系统层面上的,操作系统需要等待网络的传输等, 所以外部的工作者也就是操作系统的线程, 所以我们的应用里面只有一个工作线程,异步的时候,这个工作线程就可以去处理其他工作了。

 

解答

 

async 不是省线程么,为什么说必然会出现2个线程?

 

对。 省线程, 比如上述的异步例子,你用parallel 是不是要雇佣12个工人,才能达到相同的工作效率。

 

async 不是单线程么, 怎么你说俩线程?

 

async所说的单线程是指的 应用程序内的 “工作线程” , 真正的异步,每个人确实只有一个工作线程在干活

 

js 这种单线程语言为啥可以用异步?

 

不错, js /ts 是单线程的语言, 但是浏览器可不是单线程, 比如 setTimeout() setInterval() 他们的定时器都不在js引擎里面,而是外部的定时线程,但是回调执行时,会插入到 js 的单线程模式里面

 

 

相关资讯
济南做网站,济南做公众号,济南做小程序 首选金昇网站
金昇网站是一家在济南做网站、公众号、小程序的公司