news 2026/7/20 17:13:07

GO_并发编程---Goroutine

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
GO_并发编程---Goroutine

一、前言:Go 语言的核心优势 —— 原生并发

Go 被称为21 世纪的 C 语言,两大核心亮点:

  1. 语法设计简洁、上手门槛低
  2. 语言层面原生支持并发,内置 GC 自动垃圾回收,无需手动管理内存

Go 并发设计哲学

不同于传统多线程靠实现同步,Go 采用通信的方式解决并发竞争:

不要通过共享内存来通信,而要通过通信来共享内存

二、基础概念:并发 vs 并行

1. 并行(Parallelism)

同一时刻,多条指令在不同 CPU 核心同时执行,必须依赖多核硬件。

2. 并发(Concurrency)

同一时刻只有一条指令在 CPU 执行,系统通过时间片轮转快速切换多个任务;宏观看起来多个任务同时运行,微观是交替执行,单核 CPU 即可实现。

举例:单核 CPU 处理 3 个 1s 任务,靠时间片切换实现并发,在有限硬件资源下提升整体处理效率。

核心区分总结

  • 并发:同时处理多件事(单核、任务切换)
  • 并行:同时做多件事(多核、真正同时执行)

三、Goroutine(协程):Go 并发核心

1. 什么是 Goroutine

Goroutine 是 Go 内置的轻量级协程,可简单理解为轻量任务,是 Go 并行调度的核心:

  • 比操作系统线程体积更小、开销极低;
  • 底层采用 M:N 调度:成千上万个 goroutine 会复用少量 OS 线程;
  • Go 运行时自动管理 goroutine 内存共享,调度成本远低于线程;
  • 优势:易用、高效、资源占用极少。

2. 创建 Goroutine

语法:在函数 / 匿名函数前加go关键字,即可新建子协程。

go

// 普通函数开启协程 go newTask() // 匿名函数协程(必须加()执行) go func() { // 协程业务逻辑 }()

3. 核心规则:主协程退出,所有子协程直接销毁

main函数本身是主协程,一旦 main 执行完毕,整个进程直接终止,所有未执行完成的子协程会被强制杀死,不会等待。

示例 1:子协程来不及执行

go

package main import "time" func newTask() { for { fmt.Println("子协程运行中") time.Sleep(time.Second) } } func main() { // 开启子协程 go newTask() // 主协程循环2次就退出 i := 0 for { i++ fmt.Println("主协程 i = ", i) time.Sleep(time.Second) if i == 2 { break // main结束,子协程直接销毁,无任何输出 } } }
示例 2:死循环阻塞主协程(测试用)

写无限for{}阻塞主协程,防止程序提前退出,方便观察子协程输出:

go

func main() { go newTask() // 死循环阻塞主线程 for {} }

四、runtime 包:协程调度控制工具

1. runtime.Gosched ():主动让出 CPU 时间片

作用:当前 goroutine 主动放弃执行权,调度器切换其他就绪协程运行,等其他协程执行完毕后再切回当前协程。

示例:不加 Gosched 时,主协程会优先跑完,子协程无执行机会

go

package main import ( "fmt" "runtime" ) func main() { go func() { for i := 0; i < 5; i++ { fmt.Println("子协程 go") } }() for i := 0; i < 2; i++ { fmt.Println("主协程 hello") runtime.Gosched() // 主动让出时间片,让子协程先执行 } }

2. runtime.Goexit ():终止当前协程

作用:立即结束当前所在 goroutine,不会影响其他协程;会优先执行当前协程所有 defer 延迟函数,普通return仅终止当前函数,不会退出协程。

go

package main import ( "fmt" "runtime" ) func test() { defer fmt.Println("执行defer延迟语句") // runtime.Goexit() // 终止整个子协程 return // 仅退出test函数,协程继续往下执行 fmt.Println("该行永远不会打印") } func main() { go func() { fmt.Println("子协程开始") test() fmt.Println("子协程结束") // Goexit()时该行不会执行 }() // 死循环阻塞主协程 for {} }

3. runtime.GOMAXPROCS (n):设置并行 CPU 核心上限

  • 功能:设置可并行执行 goroutine 的 OS 线程最大数量,返回修改前的旧值;
  • 规则:
    1. n=1:单核运行,无真正并行,仅时间片切换并发;
    2. n 等于 CPU 物理核数:最大化多核并行能力;
    3. Go1.5 + 默认值为机器 CPU 核心数;
  • 效果:核数越大,多协程交替输出越混乱,并行效率越高。

go

package main import ( "fmt" "runtime" ) func main() { // 设置仅使用1核CPU,返回旧配置 old := runtime.GOMAXPROCS(1) fmt.Println("修改前CPU并行数:", old) for { go fmt.Print(1) fmt.Print(0) } }

五、多协程资源竞争问题

场景模拟:多个协程共用同一个打印机(公共资源)

多个 goroutine 同时操作同一共享资源,会出现输出错乱、数据混乱,即并发竞争,需要同步机制解决。

go

package main import "fmt" // 公共打印机资源 func Printer(str string) { for _, data := range str { fmt.Print(string(data)) } fmt.Println() } func person1() { Printer("hello") } func person2() { Printer("world") } func main() { // 两个协程同时抢占打印机,输出错乱 go person1() go person2() // 阻塞主协程观察效果 for {} }

解决方案预告

Go 官方推荐使用channel 通道实现 goroutine 同步与通信,解决资源竞争,下一章详细讲解。

六、全文总结(面试 / 复习速记)

  1. Go 核心优势:语言原生并发,goroutine 轻量高效,GC 自动回收;
  2. 并发:单核时间片切换;并行:多核同时执行;
  3. goroutine 创建:go + 函数,主协程退出则所有子协程销毁;
  4. runtime 三大工具:
    • Gosched():主动让出 CPU;
    • Goexit():终止当前协程,执行 defer;
    • GOMAXPROCS():控制并行 CPU 核心数;
  5. 多协程访问公共资源会产生竞争,使用 channel 通信实现同步。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/20 17:11:45

C语言自增运算符深度解析:从原理到指针应用与避坑指南

在C语言的学习和项目开发中&#xff0c;你是否曾对i和i的区别感到困惑&#xff1f;或者在复杂的表达式里&#xff0c;因为自增运算符的副作用而导致程序结果与预期不符&#xff1f;自增&#xff08;&#xff09;和自减&#xff08;--&#xff09;运算符是C语言中最基础也最易出…

作者头像 李华
网站建设 2026/7/20 17:09:31

WorthBase(家底)技术架构全解析:一款本地优先的个人财务 App

文章目录WorthBase&#xff08;家底&#xff09;技术架构全解析&#xff1a;一款本地优先的个人财务 App为什么做 WorthBase技术选型为什么选 SQLite 而不是 AsyncStorage&#xff1f;为什么选 Zustand 而不是 Redux&#xff1f;项目架构数据模型核心特性速览开源地址WorthBase…

作者头像 李华
网站建设 2026/7/20 17:08:26

docker compose端口暴露才能外界访问(https为例子)

由于客户端升级了谷歌相关的sdk&#xff0c;要求请求都必须是https&#xff0c; 我其实ktor中已经监听了https的端口&#xff0c;却测试不行&#xff0c;最后发现&#xff1a;必须docker compose中声明下端口才行。

作者头像 李华
网站建设 2026/7/20 17:05:43

Drain3性能优化实践:内存控制与LRU缓存策略深度调优

Drain3性能优化实践&#xff1a;内存控制与LRU缓存策略深度调优 【免费下载链接】Drain3 A robust streaming log template miner based on the Drain algorithm 项目地址: https://gitcode.com/gh_mirrors/dr/Drain3 Drain3作为一个强大的流式日志模板挖掘工具&#xf…

作者头像 李华
网站建设 2026/7/20 17:05:40

Powerlevel10k:让你的终端从黑白到彩虹的魔法配置指南

Powerlevel10k&#xff1a;让你的终端从黑白到彩虹的魔法配置指南 【免费下载链接】powerlevel10k A Zsh theme 项目地址: https://gitcode.com/GitHub_Trending/po/powerlevel10k 还记得第一次打开终端时的感受吗&#xff1f;灰白的背景&#xff0c;单调的提示符&#…

作者头像 李华
网站建设 2026/7/20 17:05:16

MCSManager完整指南:5分钟快速搭建专业游戏服务器集群

MCSManager完整指南&#xff1a;5分钟快速搭建专业游戏服务器集群 【免费下载链接】MCSManager Quick deployment, distributed, multi-user, modern management panel for Minecraft and Steam game servers / 快速安装&#xff0c;分布式架构&#xff0c;多用户销售&#xff…

作者头像 李华