本篇博客是BV17V411e7Ua的学习笔记,会直接引用其部分内容,如果侵权请联系我删除
并发的概念比较宽泛,他单纯的代表计算机可以同时执行多项任务,至于怎么做到并发,则有很多不同的形式:
- 对于一个单核处理器,计算机可以通过分配时间片的方式,不同的任务交替运行,做到并发,这个过程被称作进程或者线程的上下文切换
- 对于多核处理器,我们可以在不同核心上并行的执行任务,每个任务相对独立
至于同步和异步则是两种不同的编程模型:
- 同步代表在一个任务执行完成之后,才能执行下一个任务,因此在同步中没有并发或者并行的概念
- 异步则代表不同的任务之间不会相互等待,也就是说,你在执行任务A时,也可以同时执行任务B
一个典型实现异步的方式是多线程编程:创建多个线程并启动他们,在多核环境下,每个线程会被分配到独立的核心上运行,实现真正的并行。但如果你在使用单核处理器,或者通过设置亲和力将线程绑定到某个特定的核心上,则该核心会通过分配时间片来执行这些线程,不过这些线程依然是在并发执行
需要注意的是,对于很多编程语言如JavaScript,其本身并没有多线程概念,但是通过其函数回调机制,依然可以做到单线程的“并发”
可以看到图中的fetch()函数,在调用网络资源时,程序没有等待,而是继续执行下面的代码,当获取到网络资源之后,回调函数才被调起。需要注意的是,虽然主程序和回调函数看起来是同时进行的,但他们依然是在同一个线程之中,这就是通过异步编程做到单线程“并发”的例子
而这种功能并不是JavaScript的专利,很多语言都提供了原生的异步编程方式:如C#、Rust、C++20中的co_await,Py中的asyncio等等
简而言之,对于I/O密集的应用程序如web,就会经常执行网络操作,数据库访问,这类应用就适合使用异步编程的方式,反之如果使用多线程方式,则会因为各个线程等待I/O操作而浪费大量资源,线程本身也会占用额外内存,还会有资源竞争的情况,线程的切换更会带来额外的开销
多线程编程适合于计算量密集的应用,如视频图像处理、科学计算,可以让每个核心发挥最大的功效