关于异步编程的一些概念
当谈论到异步编程的时候总是会涉及到各种概念,比如进程(process) ,线程(thread),并行(parallel) ,并发(concurrency), 协程(coroutine),刚开始学习编程的时候一直理解不了这些概念之间的区别,只知道照着文档写写Demo,现在学了操作系统之后渐渐的对这些概念认识清晰了些,所以写这篇博客来记录一下。
1. 并发 (Concurrent)
A logical flow whose execution overlaps in time with another flow is called a concurrent flow, and the two flows are said to run concurrently. More precisely, flows X and Y are concurrent with respect to each other if and only if X begins after Y begins and before Y finishes, or Y begins after X begins and before X finishes.
上面这段是从CSAPP
中对于并发的定义,只要两个数据流在时间上有重叠就可以是它们是并发的,比如使用同一台电脑一边听音乐一边在浏览器阅读文章就可以说音乐播放器和浏览器是并发运行的。需要注意的是这里并发并不是在同一时刻运行两个程序,而是在一个时间段有多个程序在运行,可以参考下面这张图。
在时间轴上面取一个点对应的只有一个程序,但是在这个时间段运行了三个程序,这里也可以说这三个程序是并发的。在几年前家用计算机的CPU还只有一个核的时候它就和上面那张图一样在同一个时刻只能运行一个程序,操作系统内核会调度这几个程序让它们一个程序运行一会儿,因为调度的速度非常快你就会觉得这几个程序在同时运行,就像过年的时候用烟火画圈圈一样,一根烟火只要速度足够快就好像真的画出一个圆。
2. 并行 (Parallel)
并行是同一时刻有多个指令同时执行,所以并行需要使用多核CPU才能实现,因为同一时刻可以执行多条指令所以在同一时间段自然可以运行多个程序,所以满足并行则一定满足并发。换句话说,并发是同时处理各种事情,而并行是同时做各种事情。
3. 进程 (Process)
进程是一个程序的实例,当一个程序执行之后操作系统内核就会为它创建一个进程,一个进程包括程序数据和用于存储数据的栈(stack)和堆(heap),它直接受系统内核所调度的。
4. 线程 (Thread)
线程是进程里面的一条逻辑流,不同的线程之间共用一个内存空间,一个进程里面可以有多个线程并至少有一个线程,同进程一样线程同样是被内核调度。线程与进程主要的区别在于它们使用的资源不同,下面这个表格是stackoverflow
中关于线程与进程占用资源的一个总结
Per process items | Per thread items |
---|---|
Address space | Program counter |
Global variables | Registers |
Open files | Stack |
Child processes | State |
Pending alarms | |
Signals and signal handlers | |
Accounting information |
为什么有了进程还要有线程
- 不同的线程之间共用一个内存空间更加节约资源
- 因为线程比进程占用的资源要少所以线程的切换速度也比进程要快
- 因为线程之间共用内存空间与其他资源(比如文件),所以线程之间的通讯和合作更加方便
5. 协程 (Coroutine)
With coroutines, the programmer and programming language determine when to switch coroutines; in other words, tasks are cooperatively multitasked by pausing and resuming functions at set points, typically (but not necessarily) within a single thread.
协程是最近非常火的一个概念,就像以前计算机只有单核但是可以通过进程调度来实现并发,协程则是在单线程的基础上通过程序本身的调度来实现多个数据流的并发。协程相对于线程的优势在于它所用的资源更少,虽然线程相对于进程所耗资源要少一些但是它并不是免费的,就像上面介绍线程所说的,每一个线程有它们自己独有的栈空间如果线程过多会消耗大量的资源,并且操作系统还会对线程的数量进行限制,而协程是由程序语言所决定的,想要多少协程就可以有多少协程,并且协程所有资源都是共用的资源利用率更高。还有一点就是线程是由操作系统的内核所自动调度的,而协程是由程序或者程序语言所调度的,所以程序本身对协程的调度更加灵活。