当前位置: 首页 > news >正文

为什么 goroutine 比线程轻?

前言

很多人听说:

goroutine 很轻,可以开几十万

但为什么轻?到底轻在哪里?

我们从 内存、创建成本、切换成本、调度方式 四个维度拆开讲清楚。


一、最核心的一句话

goroutine 轻,是因为它是用户态调度 + 小栈 + 自己管理切换。

而线程:

是内核调度 + 大栈 + 内核切换。

差别非常大。


二、第一点:栈空间小(最直观)

线程的栈

操作系统线程:

  • 默认栈大小通常 1MB~8MB
  • 一创建就分配好
  • 不会自动缩小

如果你开 10 万个线程?

1MB × 100000 = 100GB

直接爆内存。


goroutine 的栈

goroutine:

  • 初始栈只有 2KB(不同版本略有差异)
  • 按需自动扩容
  • 可以自动收缩

例如:

  • 只调用几层函数 → 一直是 2KB
  • 深度递归 → 自动扩展
  • 用完 → 可能回收

这就是“可增长栈”。


三、第二点:创建成本低

创建线程时发生什么?

创建 OS 线程需要:

  1. 内核分配栈
  2. 创建 TCB(线程控制块)
  3. 注册调度器
  4. 系统调用
  5. 内核态切换

是一次“重量级系统调用”。


创建 goroutine 时?

创建 goroutine:

  1. 分配一个 G 结构体
  2. 分配小栈
  3. 加入 P 的队列

没有系统调用。

完全在用户态完成。

所以:

  • 开线程:微秒级甚至更高
  • 开 goroutine:纳秒级

四、第三点:切换成本低(非常关键)

线程切换是:

内核调度

会发生:

  • 用户态 → 内核态
  • 保存寄存器
  • 切换页表
  • 刷新 TLB
  • cache 失效

成本非常高。


goroutine 切换是:

runtime 调度

只需要:

  • 保存少量寄存器
  • 切换栈指针
  • 更新 G 状态

没有内核参与。

属于“用户态协程切换”。

开销小得多。


五、第四点:调度方式不同

线程:

由操作系统调度

调度器不理解你的程序逻辑。


goroutine:

由 Go runtime 调度

它知道:

  • 哪些 G 阻塞
  • 哪些 G 等待 channel
  • 哪些 G 正在 syscall
  • GC 什么时候需要暂停

调度更智能。


六、用一个对比表彻底看清

维度 线程 goroutine
栈大小 1MB~8MB 2KB 起步,自动扩容
创建成本 系统调用 用户态分配
切换成本 内核态 用户态
调度者 操作系统 Go runtime
数量级 几千 几十万

七、真正本质原因

如果用一句话概括:

goroutine 是 M:N 调度模型。

意思是:

M 个线程
调度
N 个 goroutine

例如:

8 个线程
调度 100000 个 goroutine

线程数量 ≈ CPU 核心数
goroutine 数量 ≫ 线程数

所以:

goroutine 并不是“更轻的线程”,它是被复用在少量线程上的任务。


八、为什么 Java 线程重?

因为 Java 线程就是:

1:1 映射到操作系统线程

一个 Java 线程 = 一个内核线程

所以不能开太多。


九、一个形象类比

线程像:

每个任务都单独租一辆卡车。

goroutine 像:

共享几辆卡车,任务轮流上车。

当然后者更省资源。


十、一个容易误解的点

很多人以为:

goroutine 比线程快。

这不完全准确。

如果只有一个任务:

  • 线程和 goroutine 差别几乎没有

goroutine 的优势在:

  • 大量并发
  • 高 I/O
  • 轻量任务

十一、真正的“轻”来自哪里?

可以记住这三条:

小栈
用户态切换
M:N 调度

这三点共同决定了它轻。


十二、但它也不是没有代价

  • 过多 goroutine 会导致调度开销增加
  • GC 扫描栈数量会变多
  • 仍然受 GOMAXPROCS 限制

所以:

goroutine 轻,但不是免费。


十三、终极总结

goroutine 之所以轻:

  1. 小栈(2KB 起步)
  2. 动态栈增长
  3. 用户态创建
  4. 用户态切换
  5. M:N 调度复用线程

这五点叠加,才造就了“几十万 goroutine”。

http://www.jsqmd.com/news/356006/

相关文章:

  • 已有安全措施确认(上)
  • 薅羊毛攻略:1点点奶茶怎么喝划算?美团活动揭秘,省钱吃到飞起! - Top品牌推荐
  • N32CUBE生成的代码缺少时钟配置,导致I2S不工作解决办法
  • 【小程序毕设全套源码+文档】基于Android的“康益”健身助手的设计与实现(丰富项目+远程调试+讲解+定制)
  • 1点点怎么点更便宜?美团“拼好饭”和“半价周末”让你省钱又省心! - Top品牌推荐
  • 破阵阁aaa
  • 实用指南:Spring Boot 集成 mybatis 浅析
  • N32H473REL7 使用GPIO模拟I2C配置 HTM1650
  • Uniswap_V3
  • 奶茶自由不是梦!1点点无门槛红包轻松领,美团超值优惠让你喝到爽! - Top品牌推荐
  • 2026年2月工业多聚磷酸公司推荐,专业智造与质量保障化工行业之选 - 品牌鉴赏师
  • Day30事件流,事件捕获,事件冒泡和阻止冒泡
  • 2026年2月五氧化二磷25KG桶装公司推荐,专业化工生产与品牌保障口碑之选 - 品牌鉴赏师
  • 数字图像处理篇---亮度
  • 游记:GZ ICPC2024
  • 【小程序毕设全套源码+文档】基于Android的共享雨伞租赁系统的设计与实现(丰富项目+远程调试+讲解+定制)
  • 【小程序毕设全套源码+文档】基于Android的高校二手商品交易平台的设计与实现(丰富项目+远程调试+讲解+定制)
  • 细胞多尺度仿真软件:CellSys_(9).高级建模技术
  • 细胞多尺度仿真软件:CellSys_(5).细胞动力学与运动行为模拟
  • 【小程序毕设全套源码+文档】基于Android的涪陵区特色农产品交易系统小程序的设计与实现(丰富项目+远程调试+讲解+定制)
  • 开发板挂载ubuntu 20.04 nfs Connection refused
  • 【小程序毕设源码分享】基于springboot+小程序的哈尔滨中心医院用户移动端的设计和实现小程序(程序+文档+代码讲解+一条龙定制)
  • 【小程序毕设源码分享】基于springboot+小程序的“康益”健身助手的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 【小程序毕设源码分享】基于springboot+小程序的广西文化传承小程序的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 细胞多尺度仿真软件:CellSys_(4).细胞信号传导的仿真
  • 【小程序毕设源码分享】基于springboot+小程序的汉服交易小程序的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 细胞多尺度仿真软件:CellSys_(1).细胞多尺度仿真的基础概念
  • 从铁匠铺到智能工厂:校平机技术的千年进化史
  • 细胞多尺度仿真软件:CellSys_(2).CellSys软件安装与配置
  • day79(2.7)——leetcode面试经典150