进程、线程以及Goroutine的区别

进程、线程、协程

从内存、执行单元以及切换成本三个角度来考虑

内存

  • 进程

      操作系统会以进程为单位,分配系统资源(CPU时间片、内存等资源),进程是资源分配的最小单位。
      进程的安全性比较⾼
      通信成本就比较⼤(通过IPC):
      		信号
      		管道
      		共享内存
      		socket⽹络通信
      		共享⽂件
    
  • 线程

      操作系统调度(CPU调度)执⾏的最小单位。
      共享资源,隔离性差
      通信成本比较小 通过同步机制访问共享资源即可完成通信
      线程是寄生在进程之上的
    

执行单元

  • 操作系统并不区分进程和线程区别
  • 对于同⼀个操作系统⽽⾔,如果⼀个进程开辟的线程多,那么抢占到cpu的资源就越多

切换成本

开销

  • 线程切换

      保存寄存器中的内容
      CPU⾼速缓存失效
    
  • 协程切换

      ⽤户态下的切换,实际上就是⼀个寄存器的加载
    

(1)协程切换完全在⽤户空间进⾏,线程切换涉及特权模式切换,需要在内核空间完成
(2)协程切换相⽐线程切换做的事情更少,线程需要有内核和⽤户态的切换,系统调⽤过程
(3)⼀般⼀个协程切换的时间在⼏⼗ns(纳秒量级),⼀个线程切换时间在⼏⼗~千μs(微秒量级)

大小

  • 进程 GB量级
  • 线程 MB量级
  • 协程 KB量级

不控制goroutine数量引发的问题

Goroutine

  • 体积轻量
  • 优质的GMP调度

无限开辟goroutine

  • CPU的使⽤率上升
  • Memory占⽤不断上升
  • 主进程崩溃(被强制杀死)

限制goroutine数量的方法

方法一: 只使用buffer和channel来限制

进程、线程以及Goroutine的区别
进程、线程以及Goroutine的区别

  • 弊端:如果task任务少,main先退出,由于没有同步机制,main会导致进程退出,很多在跑的go就会强制退出,任务执⾏不全。

方法二: 只使用 sync同步机制 来限制

单纯使⽤sync的waitGroup是⽆法限制go的数量的!

方法三: channel和sync的组合方式来限制

在⽅法⼀的基础上,加上同步机制。
进程、线程以及Goroutine的区别

方法四:无缓冲channel和任务发送/执行分离来限制(工作池)

进程、线程以及Goroutine的区别
进程、线程以及Goroutine的区别
将任务的发送和执⾏做了业务上的分离

  • 输⼊SendTask的频率可以设置
  • 输出执⾏task的Goroutins是数量也是可以设置
上一篇:Golang进阶实战编程(学完基础必看)视频教程


下一篇:Goroutine的深入浅出