线程与协程

线程与协程线程与协程概念进程【进程间通信(IPC)】线程协程区别场景计算密集型IO密集型两种操作如何优化哪些语言对多协程的支持概念进程二进制可执行文件在计算机内存里的一个运行实例

概念

进程

二进制可执行文件在计算机内存里的一个运行实例。比如.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 发明并用于构建汇编程序, 说明协程是一种编程思想,并不局限于特定的语言。
协程不是被操作系统内核所管理,而完全是由程序所控制(也就是在用户态执行)有自己的寄存器上下文和栈。协程切换时,
将寄存器和栈保存到其他地方,等切回来的时候,恢复保存到寄存器上下文和栈。

  1. 程序可以控制协程的暂停,如Python关键字yield,Go关键字go,都可实现协程暂停,而线程的阻塞是有操作系统控制。
  2. 在任务调度上,协程是弱于线程的。但是在资源消耗上,协程则是极低的。一个线程的内存在 MB 级别,而协程只需要 KB 级别。而且线程的调度需要内核态与用户的频繁切入切出,资源消耗也不小。

区别

对操作系统来说,线程是最小的执行单元,进程是最小的资源管理单元。

在这里插入图片描述
在这里插入图片描述

  • 并发:CPU在若干程序间多路复用,本质是cpu通过时间片进行切换。
  • 并行:若干线程同一时刻发生。

在这里插入图片描述

  1. 程序可以控制协程的暂停,如Python关键字yield,Go关键字go,都可实现协程暂停,而线程的阻塞是有操作系统控制。
  2. 在任务调度上,协程是弱于线程的。但是在资源消耗上,协程则是极低的。一个线程的内存在 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

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注