typora/note/Go/协程与线程对比.md
2024-12-12 10:48:55 +08:00

1.6 KiB
Raw Blame History

内存占用

  • 创建一个 goroutine 的栈内存消耗为 2 KB(Linux AMD64 Go v1.4后),运行过程中,如果栈空间不够用,会自动进行扩容。
  • 创建一个 thread 为了尽量避免极端情况下操作系统线程栈的溢出,默认会为其分配一个较大的栈内存( 1 - 8 MB 栈内存POSIX Thread),而且还需要一个被称为 “guard page” 的区域用于和其他 thread 的栈空间进行隔离。而栈内存空间一旦创建和初始化完成之后其大小就不能再有变化,这决定了在某些特殊场景下系统线程栈还是有溢出的风险。

创建和销毁

  • 线程创建和销毀都会有巨大的消耗,是内核级的交互(trap)。进入内核所消耗的性能代价比较高,开销较大。
  • goroutine 是用户态线程,是由 go runtime 管理,创建和销毁的消耗非常小。

调度切换

  • 抛开陷入内核,线程切换会消耗 1000-1500 纳秒(上下文保存成本高,较多寄存器,公平性,复杂时间计算统计),一个纳秒平均可以执行 12-18 条指令。所以由于线程切换,执行指令的条数会减少 12000-18000。
  • goroutine 的切换约为 200 ns(用户态、3个寄存器),相当于 2400-3600 条指令。因此goroutines 切换成本比 threads 要小得多

复杂性

  • 线程的创建和退出复杂多个thread间通讯复杂(share memory)
  • 不能大量创建线程成本高使用网络多路复用存在大量callback。对于应用服务线程门槛高例如需要做第三方库隔离需要考虑引入线程池等