线程
- 线程是CPU调度的最小单位
CPU 执行过程图
- 比如我们有一个
单核CPU
,目前有3个想要执行的线程,这3个线程在执行过程中先执行1,在下一个时间片cpu让渡出来执行线程2,在下一个时间片cpu让渡出来执行线程3,以此类推,最终将3个线程执行完毕。 - 如果我们不将CPU进行分片,按顺序先执行完线程1,再执行线程2,最后执行线程3。
- 我们是否有一个疑惑,
前者(CPU切片)
和后者(顺序执行)
使用的时间貌似是一样的,并且后者(顺序执行)
只切换了2次上下文,这样是不是执行的效率更高呢?那多线程存在的意义有体现在哪里呢? - 提到了上面的疑问,我们就不得不说道一下
I/O
(磁盘的读写、网络的数据传输、音视频的输入输出等),那么我们在编程的中的I/O主要是磁盘I/O
和网络I/O
,I/O
是非常耗时间的。
- 假如我们有CPU、硬盘、内存,要想文件读取,我们最先想到的是CPU直接读取硬盘数据放入内存的变量中,这样在整个读取的过程中整个I/O都被占用的,因而这种方式会造成
前者(CPU切片)
和后者(顺序执行)
执行效率差不多的。 - 但是实际的I/O并不是这样的,实际的I/O的过程中有一个非常重要的东西
DMA控制器
。在读取文件的过程中,其实CPU不会直接操作硬盘,而是给DMA控制器
下达命令来完成文件的读取。首先,CPU 对DMA下达指令(这个指令中包含有磁盘设备信息和要读取的文件位置信息),然后DMA告知硬盘进行文件读取并将读取的文件内容加载到内存变量中,读取完毕之后硬盘会返回反馈一个读取结果完成的信息给到DMA,DMA之后以终端的形式通知CPU,然后CPU去内存中拉取数据,最终拿到数据。
- 我们通过步骤一下达指令之后,其实CPU就处于闲置状态,就可以执行其他线程。我们现在再此回看单核cpu处理3个线程读取文件,CPU下达指令给DMA后(CPU闲置),假如线程2拿到CPU控制权,同样CPU下达指令给DMA后(CPU闲置),线程3拿到CPU控制权,同样CPU下达指令给DMA后(CPU闲置),CPU可以执行其他线程,最终实现并行读取,提高CPU利用率。另外,DMA进行数据读取是可以复用的,CPU的总线具有多条线路,DMA就可以充分利用这些线路,最终实现并行的读取文件。
协程
- 协程是类似于编程语言级别的线程,一种用户态的轻量级线程,协程不像线程和进程需要进行系统内核上的上下文切换,协程的上下文切换是由用户自己决定的,有自己的上下文,所以说是轻量级的线程,也称之为用户级别的线程就叫协程,一个线程可以多个协程,线程进程都是同步机制,而协程则是异步。协程没有用户态和内核态的转化,性能会比线程效率更高。
异步
- cpu 发送指令给DMA就是异步执行读取文件,cpu则会被空闲出来执行别的线程。程序级别的也有很多异步操作,比如充值成功短信通知用户的操作,一般都是异步存于队列。
2 comments
进程
就是我们执行的程序。程序和程序之间没有共享内容,都是自己独立的内存空间。
调度切换由操作系统完成,用户无感知,切换内容非常多,开销大,效率低。
需要通信的话一般是通过信号传递,或者外部工具。
线程
进程下面的小弟,同一个进程间的多个线程共享内存。
真正的并行执行,可以利用 CPU 的核数。
调度切换比进程小,但一样是操作系统完成,开销和效率中等。
协程
线程的小弟,但其实更像是一个函数。
在线程之上的串行运行,依赖于线程,而且依赖于异步 IO ,如果没有 异步IO 的支持,它和线程没什么区别。
更加轻量级,用户态切换,开销成本低,效率非常高。
协程只是说在一个线程中,通过自己控制自己,来让一个线程中可以执行多个协程程序,当前面的协程阻塞时,通过异步 IO 放在那里去执行,然后切换到其它的协程运行。在这个时候,操作系统并不需要切换或者创新新的线程,减少了线程的切换时间。注意,真正并行的只有线程,或者两个不相干的进程,而协程,并不是并行处理的,在线程中,它也是在 CPU 的时间分片机制下的切换执行。一个线程中的一个协程运行时,其它的协程是挂起状态的。它的切换成本非常低,而且是用户态可控的。协程和进程、线程完全不是一个维度的概念,它就是个函数。