0

0

Go并发编程与多线程有什么区别_Go调度模型详解

P粉602998670

P粉602998670

发布时间:2026-01-18 16:47:35

|

722人浏览过

|

来源于php中文网

原创

goroutine 是 go 运行时 gmp 模型管理的用户态并发单元,创建开销仅 20–50 ns(栈 2kb),远低于 os 线程的 1–5μs(栈 2mb),支持单机十万级并发;其非阻塞调度依赖 runtime 封装系统调用并解耦 m,通信首选 channel 而非锁,避免竞态与死锁。

go并发编程与多线程有什么区别_go调度模型详解

Go 的 goroutine 不是线程,也不是“轻量级线程”的简单替代;它是运行时调度器(GMP)管理下的用户态并发单元,和操作系统线程存在本质的调度关系、资源模型与通信范式差异。

goroutine 和 OS 线程的创建开销差多少?

创建一个 goroutine 平均耗时约 20–50 ns,初始2KB(可动态扩缩);而调用 pthread_create 创建一个 OS 线程,通常需 1–5μs,且默认栈空间为 2MB(Linux 下常见)。这意味着:你可以在单机上安全启动 100,000+ 个 goroutine,但超过 10,000 个 OS 线程就极易触发 ENOMEM 或调度抖动。

  • 实操建议:别用 go f() 启动无限循环且无退出逻辑的 goroutine,哪怕它很“轻”——泄漏的 goroutine 会持续占用堆内存(如闭包捕获大对象)
  • 验证方式:运行时可通过 runtime.NumGoroutine() 观察数量,配合 pprof 查看 goroutine stack trace
  • 注意:GOMAXPROCS 控制的是“可并行执行的 OS 线程数”,不是 goroutine 数量上限;它影响的是并行度,而非并发能力

为什么 goroutine 不会因系统调用阻塞整个线程?

Go 运行时对多数阻塞系统调用(如文件 I/O、网络读写、time.Sleep)做了封装,当某个 goroutine 调用这些函数时,运行时会将其从当前 OS 线程(M)上剥离,并把该线程交还给其他 goroutine 使用,同时将阻塞的 goroutine 挂起在 netpoller 或 timer heap 上。这依赖于 Go 的 non-blocking I/O + epoll/kqueue/IOCP 底层支持。

Designs.ai
Designs.ai

AI设计工具

下载
  • 常见错误现象:用 os.Open 打开一个 NFS 挂载点上的慢设备文件,若未设超时,可能卡住整个 M —— 因为部分 syscall 无法被异步化(如某些磁盘 I/O)
  • 规避方法:优先使用 net/httpdatabase/sql标准库封装好的带 context 支持的 API;自定义阻塞操作务必包裹在 runtime.LockOSThread() + 单独 goroutine 中隔离
  • 关键区别:Java 线程遇到 read() 阻塞,整个线程(含 JVM 栈)直接让出 CPU 给 OS 调度器;而 Go 是在用户态完成“解耦-重调度”,无需陷入内核

channel 通信 vs 共享内存 + 锁,到底省了什么?

channel 不是“语法糖”,它是 Go 运行时内置的同步原语,底层由环形缓冲区 + g 队列 + 自旋/休眠状态机实现。它强制你显式声明数据流向(chan int)、所有权转移(发送即移交)和同步点(阻塞收发),天然规避了竞态、死锁(部分)、忘记 unlock 等问题。

  • 典型坑:用 sync.Mutex 保护 map 时,忘了加 defer mu.Unlock() 或 panic 后没 recover,导致锁永远不释放;而 ch 天然具备原子性与上下文感知
  • 性能提示:无缓冲 channel 的 send/receive 是完全同步的(即配对 goroutine 直接交接),比 mutex + condvar 更快;有缓冲 channel 在缓冲未满/非空时可零拷贝快速通行
  • 慎用场景:高频、小数据、确定无等待的跨 goroutine 传值,可考虑 unsafe.Pointer + atomic.Store/Load,但 channel 仍是绝大多数场景下最安全、最易推理的选择

GMP 模型里,P 到底管什么?

P(Processor)是 Go 调度器的核心抽象,它代表“可运行 goroutine 的逻辑上下文”,每个 P 绑定一个本地运行队列(runq)、一个全局队列(globrunq)、以及 netpollertimer 管理权。它不对应 CPU 核心,但数量默认等于 GOMAXPROCS(即最大并行线程数)。

  • 关键事实:一个空闲的 P 可以被任意空闲 M(OS 线程)获取来执行 goroutine;当 M 遇到系统调用阻塞时,它会尝试将绑定的 P 转交给其他 M,自己进入休眠 —— 这就是“M 可以远多于 P,P 可以复用 M”的基础
  • 调试线索:若观察到 runtime.GC 频繁或 schedtrace 显示大量 P 处于 _Pidle 状态但 M 很少,说明 goroutine 大量阻塞在非可调度操作(如 C 代码、syscall.Syscall)上
  • 不要手动调 runtime.GOMAXPROCS(n) 来“提升性能”:现代 Go 默认已设为 CPU 核心数;盲目调高只会增加 P 切换开销,调低则浪费并行能力

真正难的不是理解 GMP 三字母,而是判断什么时候该让 goroutine 等待 channel,什么时候该用 context.WithTimeout 主动取消,以及——当 pprof 显示 90% 时间花在 runtime.futex 上时,你得意识到那根本不是 goroutine 的问题,而是你在用 sync.RWMutex 锁住了整个服务请求链路。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

1090

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

340

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

380

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2028

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

379

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

1560

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

585

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

438

2024.04.29

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

33

2026.03.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 10.1万人学习

Git 教程
Git 教程

共21课时 | 4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号