进程、线程、协程

进程、线程、协程

1、对比

进程、线程、协程都是计算机中用于实现多任务的概念,它们之间有如下的区别和对比:

  1. 进程(Process)是计算机中资源分配和调度的基本单位,每个进程都有独立的内存空间,相互之间互不干扰,具有独立的执行流程和系统资源。**进程之间通信需要借助于进程间通信(IPC)的机制,如管道、信号、消息队列、共享内存等。**切换开销大。
  2. **线程(Thread)是进程的子任务,是操作系统调度的基本单位,每个线程都共享所属进程的内存空间,**彼此之间可以共享内存和资源。**线程之间通信需要借助于同步原语(如锁、信号量等)来进行协调,以防止线程之间的竞争和冲突。**切换开销小。
  3. **协程(Coroutine)是一种轻量级的线程,也称为用户级线程,不需要操作系统的调度,而是由程序本身控制调度。**协程具有比线程更小的上下文切换开销和更高的并发性能,因为在协程中,切换是由程序自身控制的,而不需要进行系统调用。**协程之间通信也可以使用同步原语来进行协调。**切换开销最小。

2、进程

在程序启动时,操作系统会给该程序分配一块内存空间,对于程序但看到的是一整块连续的内存空间,称为虚拟内存空间,落实到操作系统内核则是一块一块的内存碎片的东西。为的是节省内核空间,方便对内存管理。

img

就这片内存空间,又划分为用户空间与内核空间,**用户空间只用于用户程序的执行,若要执行各种IO操作,就会通过系统调用等进入内核空间进行操作。**每个进程都有自己的PID,可以通过ps命令查看某个进程的pid。

3、线程

线程是进程的一个执行单元,一个进程可以包含多个线程,只有拥有了线程的进程才会被CPU执行,所以一个进程最少拥有一个主线程。

image-20230502211923912

​ 由于多个线程可以共享同一个进程的内存空间,线程的创建不需要额外的虚拟内存空间,线程之间的切换也就少了如进程切换的切换页表,切换虚拟地址空间此类的巨大开销。

​ 至于进程切换为什么较大,简单理解是因为进程切换要保存的现场太多如寄存器,栈,代码段,执行位置等,而线程切换只需要上下文切换,保存线程执行的上下文即可。线程的的切换只需要保存线程的执行现场(程序计数器等状态)保存在该线程的栈里,CPU把栈指针,指令寄存器的值指向下一个线程。相比之下线程更加轻量级。

​ 可以说进程面向的主要内容是内存分配管理,而线程主要面向的CPU调度。

4、协程

​ 虽然线程比进程要轻量级,但是每个线程依然占有1M左右的空间,在高并发场景下非常吃机器内存,比如构建一个http服务器,如果一个每来一次请求分配一个线程,请求数暴增容易OOM(out of memery),而且线程切换的开销也是不可忽视的。同时,线程的创建与销毁同样是比较大的系统开销,因为是由内核来做的,解决方法也有,可以通过线程池或协程来解决。

协程是用户态的线程,比线程更加的轻量级,操作系统对其没有感知,之所以没有感知是由于协程处于线程的用户栈能感知的范围,是由用户创建的而非操作系统。

​ Golang里的goroutine是对协程的抽象,相比于其他n-1的协程,一个协程阻塞可能会造成后续协程的阻塞,而Go中的goroutine与线程是N-M的关系,可以通过hand-off机制实现切换。

image-20230502212619312

这里的G为协程,P为调度器。

如一个进程可拥有以有多个线程一样,一个线程也可以拥有多个协程。协程之于线程如同线程之于cpu,拥有自己的协程队列,每个协程拥有自己的栈空间,在协程切换时候只需要保存协程的上下文,开销要比内核态的线程切换要小很多。
栈空间,在协程切换时候只需要保存协程的上下文,开销要比内核态的线程切换要小很多。**

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值