概念
进程
二进制可执行文件在计算机内存里的一个运行实例。比如.exe文件是个类,进程就是new出来的那个实例,计算机资源分配的基本单位。
进程,直观点说,保存在硬盘上的程序运行以后,会在内存空间里形成一个独立的内存体,这个内存体有自己独立的地址空间,有自己的堆,上级挂靠单位是操作系统。操作系统会以进程为单位,分配系统资源(CPU时间片、内存等资源),进程是资源分配的最小单位。
【进程间通信(IPC)】
管道(Pipe)、命名管道(FIFO)、消息队列(Message Queue) 、
信号量(Semaphore) 、共享内存(Shared Memory);套接字(Socket)。
线程
程序执行的最小单元,是由寄存器集合和堆栈组成,线程是进程中的一个实体,可共享同一进程中所拥有的全部资源。
线程,有时被称为轻量级进程(Lightweight Process,LWP),是操作系统调度(CPU调度)执行的最小单位。
-
调度
线程作为调度和分配的基本单位,进程作为拥有资源的基本单位; -
并发性
不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行; -
拥有资源
进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源。
进程所维护的是程序所包含的资源(静态资源), 如:地址空间,打开的文件句柄集,文件系统状态,
信号处理handler等;线程所维护的运行相关的资源(动态资源),如:运行栈,调度相关的控制信息,
待处理的信号集等; -
系统开销
在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于
创建或撤消线程时的开销。但是进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对
其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,
但线程之间没有单独的地址空间,一个进程死掉就等于所有的线程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。
协程
协程(coroutine)是一种程序组件,是一种比线程更加轻量级的存在。正如一个进程可以有多个线程,一个线程可以有多个协程。
「协程 Coroutines」源自 Simula 和 Modula-2 语言,这个术语早在 1958 年就被 Melvin Edward
Conway 发明并用于构建汇编程序, 说明协程是一种编程思想,并不局限于特定的语言。
协程不是被操作系统内核所管理,而完全是由程序所控制(也就是在用户态执行)有自己的寄存器上下文和栈。协程切换时,
将寄存器和栈保存到其他地方,等切回来的时候,恢复保存到寄存器上下文和栈。
- 程序可以控制协程的暂停,如Python关键字yield,Go关键字go,都可实现协程暂停,而线程的阻塞是有操作系统控制。
- 在任务调度上,协程是弱于线程的。但是在资源消耗上,协程则是极低的。一个线程的内存在 MB 级别,而协程只需要 KB 级别。而且线程的调度需要内核态与用户的频繁切入切出,资源消耗也不小。
区别
对操作系统来说,线程是最小的执行单元,进程是最小的资源管理单元。
- 并发:CPU在若干程序间多路复用,本质是cpu通过时间片进行切换。
- 并行:若干线程同一时刻发生。
- 程序可以控制协程的暂停,如Python关键字yield,Go关键字go,都可实现协程暂停,而线程的阻塞是有操作系统控制。
- 在任务调度上,协程是弱于线程的。但是在资源消耗上,协程则是极低的。一个线程的内存在 MB 级别,而协程只需要 KB 级别。而且线程的调度需要内核态与用户的频繁切入切出,资源消耗也不小。
协程优点:
节省内存
节省分配线程的开销
节省线程切换带来的开销
协程 | 线程 | 进程 | |
---|---|---|---|
原理 | 协程有自己的寄存器上下文和栈。协程切换时,将寄存器和栈保存到其他地方,等切回来的时候,恢复之前保存到寄存器上下文和栈。 | 分配CPU资源。多个线程共享堆和方法区资源,每个线程有自己的程序计数器、虚拟机栈和本地方法栈 | 分配系统资源,标识任务。进程占有的资源有:①地址空间②全局变量③文件描述符④各种硬件资源。 |
优点 | 1、无需协程上下文切换的开销2、无需原子操作锁定及同步的开销(不会被线程调度机制打断的操作)通过判断返回状态3、高并发+高扩展+低成本。注意:python中实现协程通过generater的yield实现 | 1、有独立的运行栈和程序计数器,线程之间切换开销小。2、共享进程的系统资源 | 1、有独立的上下文。2、进程之间的系统资源相互独立。3、一个进程崩溃不会影响其他的进程。 |
缺点 | 1、无法利用多核资源:协程的本质是单线程,需要线程配合才可以在多CPU上运行。2、进行阻塞操作(如IO操作)会阻塞掉整个程序 | 1、一个线程的崩溃,会影响本进程的所有线程。2、有锁机制,可能会死锁。 | 进程切换开销大,不利于资源的有效利用 |
场景
计算密集型
系统涉及大部分计算,逻辑判断,循环,导致CPU占用率高。
IO密集型
网络传输,读取硬盘,其他组件频繁交互。更实用多协程多线程的场景。
两种操作如何优化
算法优化,缓存,范围查询改为精准定位
减少IO,一次性加载
哪些语言对多协程的支持
- Lua语言
Lua从5.0版本开始使用协程,通过扩展库coroutine来实现。
- Python语言
正如刚才所写的代码示例,python可以通过 yield/send 的方式实现协程。在python 3.5以后,async/await 成为了更好的替代方案。
- Go语言
Go语言对协程的实现非常强大而简洁,可以轻松创建成百上千个协程并发执行。
- Java语言
如上文所说,Java语言并没有对协程的原生支持,但是某些开源框架模拟出了协程的功能,有兴趣的小伙伴可以看一看Kilim框架的源码
今天的文章线程与协程分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/67273.html