
在Go语言中,Goroutine是轻量级的并发执行单元,由Go运行时(runtime)负责调度。开发者常常期望通过go关键字启动的多个Goroutine能够“并排”或即时交错地执行。然而,在实际观察中,尤其是在默认配置下,可能会发现Goroutine的执行呈现出分块(chunked)而非细粒度交错的模式。这种现象揭示了Go调度器的工作原理以及GOMAXPROCS配置的关键作用。
考虑以下示例代码,它启动了两个Goroutine,每个Goroutine都在独立地计算斐波那契数列:
package main
import (
"fmt"
"runtime" // 引入runtime包
"time"
)
// fib 计算斐波那契数列的第n项,这是一个CPU密集型操作
func fib(n int) int {
if n <= 1 {
return n
}
return fib(n-1) + fib(n-2)
}
// worker 模拟一个CPU密集型任务
func worker(from string) {
for i := 0; i < 40; i++ {
// 模拟一些工作,例如计算斐波那契数列
result := fib(i)
fmt.Printf("%s fib( %d ): %d\n", from, i, result)
}
}
func main() {
// 默认情况下,Go 1.5+ 会将 GOMAXPROCS 设置为 CPU 核心数。
// 但为了演示单核行为,我们可以在此处显式设置为1
// 或者在运行程序时设置环境变量 GOMAXPROCS=1
// runtime.GOMAXPROCS(1) // 可以取消注释以强制单核调度
go worker("|||") // 启动第一个Goroutine
go worker("---") // 启动第二个Goroutine
// 等待Goroutine完成,或者通过其他机制控制程序退出
// 这里使用一个简单的等待输入来防止main Goroutine过早退出
fmt.Println("Press Enter to exit...")
var input string
fmt.Scanln(&input)
fmt.Println("Done.")
}
在某些环境下运行上述代码时(特别是当GOMAXPROCS被设置为1时),可能会观察到这样的输出模式:首先,一个Goroutine(例如---)会连续执行很长一段时间,完成其大部分甚至全部迭代;然后,另一个Goroutine(例如|||)才会接管并执行。只有在任务接近尾声时,才可能出现两个Goroutine交替执行的现象。这种行为与我们直觉中期望的随机、细粒度交错的“并行”执行有所不同。
Go运行时包含一个M:N调度器,它将多个Goroutine(M)映射到少量操作系统线程(N)上。这些操作系统线程再由操作系统的调度器映射到可用的CPU核心上。Go调度器的主要职责是管理Goroutine的生命周期,并在操作系统线程上高效地切换它们。
在默认情况下或当GOMAXPROCS设置为1时,Go调度器将所有Goroutine调度到一个操作系统线程上。这意味着,尽管有多个Goroutine,它们在任何给定时刻都只能在一个CPU核心上“并发”执行,即通过时间片轮转或协作式调度(例如,当Goroutine执行I/O操作或显式调用runtime.Gosched()时)来模拟并发。在这种单线程模型下,一个CPU密集型Goroutine可能会长时间占用CPU,直到它完成其当前任务块或Go调度器强制其让出CPU。
GOMAXPROCS是一个环境变量或可以通过runtime.GOMAXPROCS()函数设置的参数,它控制Go运行时可以使用的最大操作系统线程数。这些操作系统线程被称为“处理器”(Processor,P),每个P可以执行一个Go M(Machine,操作系统线程)上的Goroutine。
Viggle AI Video
Powerful AI-powered animation tool and image-to-video AI generator.
115
查看详情
自Go 1.5版本起,GOMAXPROCS的默认值已更改为机器上的逻辑CPU核心数。这意味着在现代Go版本中,如果系统有多个核心,Goroutine默认就会被调度到多个核心上并行执行。然而,如果开发者显式地将GOMAXPROCS设置为1,或者在某些特殊环境中,仍可能观察到单核行为。
为了让Goroutine在多核CPU上实现更接近并行的执行,最直接的方法是确保GOMAXPROCS被设置为大于1的值,通常是系统的CPU核心数。
通过环境变量设置: 在运行Go程序之前,设置GOMAXPROCS环境变量。
export GOMAXPROCS=4 # 例如,设置为4个核心 go run your_program.go
或者在Windows上:
set GOMAXPROCS=4 go run your_program.go
通过 runtime.GOMAXPROCS() 函数设置: 在程序启动时,可以通过调用runtime.GOMAXPROCS()函数来设置。通常,建议将其设置为runtime.NumCPU()返回的值,以充分利用所有可用的CPU核心。
package main
import (
"fmt"
"runtime"
"time"
)
func fib(n int) int {
if n <= 1 {
return n
}
return fib(n-1) + fib(n-2)
}
func worker(from string) {
for i := 0; i < 40; i++ {
result := fib(i)
fmt.Printf("%s fib( %d ): %d\n", from, i, result)
}
}
func main() {
// 设置 GOMAXPROCS 为可用的CPU核心数
runtime.GOMAXPROCS(runtime.NumCPU())
fmt.Printf("GOMAXPROCS set to: %d\n", runtime.GOMAXPROCS(0)) // 打印当前GOMAXPROCS值
go worker("|||")
go worker("---")
fmt.Println("Press Enter to exit...")
var input string
fmt.Scanln(&input)
fmt.Println("Done.")
}当GOMAXPROCS设置为系统CPU核心数时,再次运行上述代码,您会观察到两个Goroutine的输出更加频繁地交错出现,因为它们现在有机会在不同的CPU核心上同时执行。
Go语言的Goroutine和调度器提供了一种强大而高效的并发模型。理解GOMAXPROCS参数对于优化Go程序的性能和正确理解其并发行为至关重要。当观察到Goroutine执行呈现出分块而非细粒度交错时,通常是因为Go运行时被限制在单个操作系统线程上执行。通过合理配置GOMAXPROCS,我们可以充分利用多核CPU的优势,实现Goroutine的真正并行执行,从而提升CPU密集型应用的性能。
以上就是Go Goroutine调度与并发执行深度解析的详细内容,更多请关注其它相关文章!
# 器中
# 威海教育培训网站建设
# 福建福州市网站推广
# 宜昌seo培训
# 山西seo查询哪个适用
# 成都网站优化地址查询
# 济宁市场seo工具
# seo的kpi考核标准
# 网站推广专家工作内容
# 品牌网站推广招商加盟
# 烟台推广网站有哪些平台
# 可以通过
# 我们可以
# 会在
# 观察到
# go
# 多核
# 多个
# 设置为
# AI-powered
# 环境配置
# 区别
# win
# 环境变量
# ai
# mac
# go语言
# 处理器
# 操作系统
# windows
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
优化推广96088 】
【
技术知识133117 】
【
IDC资讯59369 】
【
网络运营7196 】
【
IT资讯61894 】
相关推荐:
邮政快递寄件查询入口 邮政快递收件查询入口
Python csv 模块处理非字符串数据:列表写入 CSV 文件的机制解析
虫虫漫画排行榜单入口_虫虫漫画编辑推荐入口
VS Code如何设置默认配置
《知到》打卡课程方法
Bootstrap 5导航栏折叠功能失效:数据属性迁移指南
猫眼app抢票快还是小程序快
电脑视频号|直播|如何分享屏幕
sublime如何自定义文件类型图标_AFileIcon插件的主题切换与个性化配置
Win11便笺在哪打开 Win11桌面便笺(Sticky Notes)使用方法【详解】
win11怎么更改账户类型 Win11标准用户和管理员权限切换【教程】
FullCalendar自定义按钮样式定制指南
优酷下载视频的清晰度怎么选_优酷缓存清晰度设置与选择指南
excel怎么计算平均值 excel平均函数*ERAGE使用教学
之了课堂app做题入口
使用Python和GBGB API高效抓取指定日期范围和赛道比赛结果教程
J*a列表元素格式化输出教程
J*aScript二进制处理_ArrayBuffer与Blob
《领英》查看屏蔽名单方法
解决异步Python机器人中同步操作的阻塞问题
uc浏览器官网网页版使用 uc浏览器官网免费在线首页
qq邮箱怎么注册_QQ邮箱注册步骤与注意事项
不吃碳水化合物是健康减肥的好办法吗
鲁班大师乓乓皮肤获取方法
铁路12306座位怎么选_12306官方选座操作方法
背部总是隐隐作痛怎么回事 背痛如何改善
Go反射进阶:访问内嵌结构体中的被遮蔽方法
HTML与J*aScript实现下拉菜单驱动的动态表格:构建交互式维修表单
智慧团建活动报名入口 智慧团建活动报名入口手机端官网
解决CSS background 属性中 cover 关键字的常见误用
小米倒班助手添加日历提醒
cad视图选项卡不见了怎么办_cad视图标签恢复显示方法
word页码灰色不能用如何解决
Linux如何优化系统启动流程_Linux启动项优化方案
鼠标没反应了怎么办 无线/有线鼠标失灵的解决方法【详解】
Pydantic 中“schema”字段命名冲突的解决方案
《环球网校》设置报考省市方法
QQ网页版入口导航 QQ网页版在线访问通道
小红书网页版首页入口 小红书网页版电脑端官方登录链接
mysql导入sql文件能分批导入吗_mysql分批次导入大sql文件的实用技巧
12306售票时间最新规定 | 网上订票和车站窗口时间一样吗
mysql归档数据怎么导出为csv_mysql归档数据导出为csv文件的方法
C++ switch case字符串_C++如何实现字符串switch匹配
Python中安全地将环境变量转换为整数的类型注解指南
怎样设置开机后自动运行某个程序_Windows启动文件夹与任务计划【自动化】
虫虫助手如何更新游戏
苹果手机如何清理系统缓存数据 iPhone非越狱清理垃圾文件的技巧【系统优化】
谷歌浏览器官网地址整理_谷歌浏览器新版直连2026稳定访问
电脑双系统如何安装和卸载 Windows和Linux双系统安装教程【详解】
歌词怎么展示在|直播|间视频号?有什么注意事项?
2025-11-29
运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。