Go 语言的并发模型是其区别于其他编程语言的重要特性之一,它以简洁高效的方式解决了现代编程中多核处理器利用和高并发场景的需求。

一、并发与并行:概念与区别

在理解 Go 的并发模型之前,需要明确并发与并行的差异:

  • 并发:指程序同时管理多个任务的能力,这些任务可能在交替执行
  • 并行:指多个任务在不同处理器上同时执行

Go 的并发模型基于 CSP(通信顺序进程)范式,通过 goroutine 和通道实现高效的并发编程。Go 运行时的调度器会将 goroutine 分配到逻辑处理器上执行,每个逻辑处理器绑定一个操作系统线程。

二、goroutine:轻量级线程的实践

1. 创建与调度

goroutine 是 Go 并发的基本单元,创建方式非常简洁:

package mainimport ("fmt""time"
)func main() {// 创建goroutine执行任务go printAlphabet("a")go printAlphabet("A")// 等待任务完成time.Sleep(2 * time.Second)
}func printAlphabet(prefix string) {for char := 'a'; char < 'a'+26; char++ {fmt.Printf("%s: %c\n", prefix, char)time.Sleep(100 * time.Millisecond)}
}

2. 调度器与逻辑处理器

Go 调度器的核心组件包括:

  • 全局运行队列:存放等待执行的 goroutine
  • 本地运行队列:每个逻辑处理器对应的运行队列
  • 网络轮询器:处理网络 I/O 相关的 goroutine

通过runtime.GOMAXPROCS函数可以设置逻辑处理器的数量:

// 设置使用2个逻辑处理器
runtime.GOMAXPROCS(2)

三、竞争状态:问题检测与解决方案

1. 竞争状态的产生

当多个 goroutine 同时访问共享资源时,可能引发竞争状态:

package mainimport ("fmt""sync"
)var counter int
var wg sync.WaitGroupfunc main() {wg.Add(2)go increment("A")go increment("B")wg.Wait()fmt.Println("Final counter:", counter) // 预期输出4,实际可能小于4
}func increment(identifier string) {defer wg.Done()for i := 0; i < 2; i++ {value := counter// 模拟上下文切换fmt.Printf("%s: Reading counter as %d\n", identifier, value)counter = value + 1}
}

2. 竞争检测工具

Go 提供了内置的竞争检测工具:

go build -race your_program.go
./your_program

3. 解决方案:原子操作与互斥锁

原子操作示例

package mainimport ("atomic""fmt""sync"
)var counter int64
var wg sync.WaitGroupfunc main() {wg.Add(2)go safeIncrement("A")go safeIncrement("B")wg.Wait()fmt.Println("Final counter:", atomic.LoadInt64(&counter))
}func safeIncrement(identifier string) {defer wg.Done()for i := 0; i < 2; i++ {atomic.AddInt64(&counter, 1)fmt.Printf("%s: Incremented counter\n", identifier)}
}

互斥锁示例

package mainimport ("fmt""sync"
)var counter int
var mutex sync.Mutex
var wg sync.WaitGroupfunc main() {wg.Add(2)go safeIncrement("A")go safeIncrement("B")wg.Wait()fmt.Println("Final counter:", counter)
}func safeIncrement(identifier string) {defer wg.Done()for i := 0; i < 2; i++ {mutex.Lock()counter++fmt.Printf("%s: Incremented counter to %d\n", identifier, counter)mutex.Unlock()}
}

四、通道:goroutine 间的通信桥梁

1. 无缓冲通道:同步通信

无缓冲通道要求发送和接收操作同时准备好,典型应用场景如任务同步:

package mainimport ("fmt""sync"
)func main() {court := make(chan int)var wg sync.WaitGroupwg.Add(2)// 启动两个选手go player("Nadal", court, &wg)go player("Djokovic", court, &wg)// 发球开始比赛court <- 1// 等待比赛结束wg.Wait()close(court)
}func player(name string, court chan int, wg *sync.WaitGroup) {defer wg.Done()for {// 等待接球ball, ok := <-courtif !ok {fmt.Printf("%s 获胜!\n", name)return}// 模拟击球fmt.Printf("%s 击球: %d\n", name, ball)ball++// 随机决定是否失误if ball%10 == 0 {fmt.Printf("%s 失误!\n", name)close(court)return}// 回击球court <- ball}
}

2. 有缓冲通道:异步通信

有缓冲通道允许发送和接收操作不同步,适合任务池场景:

package mainimport ("fmt""sync""time"
)const taskCount = 10func main() {// 创建有缓冲通道作为任务池tasks := make(chan int, taskCount)var wg sync.WaitGroupwg.Add(3) // 3个工作goroutine// 启动工作goroutinefor worker := 1; worker <= 3; worker++ {go workerTask(worker, tasks, &wg)}// 提交任务for task := 1; task <= taskCount; task++ {tasks <- taskfmt.Printf("任务 %d 已提交\n", task)}// 关闭通道表示任务提交完成close(tasks)// 等待所有任务完成wg.Wait()
}func workerTask(worker int, tasks chan int, wg *sync.WaitGroup) {defer wg.Done()for task := range tasks {fmt.Printf("工作者 %d 处理任务 %d\n", worker, task)time.Sleep(500 * time.Millisecond)}
}

五、Go 并发编程建议

  1. 优先使用通道而非共享内存:遵循 "不要通过共享内存来通信,而要通过通信来共享内存" 的原则
  2. 控制 goroutine 数量:避免创建过多 goroutine 导致资源耗尽
  3. 正确处理错误和取消:通过 context 包处理上下文取消
  4. 使用 WaitGroup 跟踪任务:确保所有 goroutine 完成后程序再退出
  5. 定期进行压力测试:使用 Go 的基准测试工具检测性能瓶颈

六、总结

Go 语言的并发模型以简洁高效的方式解决了现代软件开发中的高并发需求,通过 goroutine 和通道的组合,开发者可以轻松构建复杂的并发系统。掌握并发编程不仅能充分利用多核处理器性能,还能简化异步任务的处理逻辑。

在实际开发中,需要根据具体场景选择合适的并发模式,合理处理资源竞争和任务协调,才能发挥 Go 并发模型的最大优势。随着 Go 生态的不断发展,并发编程也将在微服务、云计算等领域发挥更加重要的作用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/86582.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/86582.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/86582.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Versoria函数优化协方差更新的改进扩展卡尔曼滤波(MVC-EKF)与经典EKF的对比,附matlab源代码|订阅专栏后可查看完整代码

本代码实现了基于Versoria函数优化协方差更新的改进扩展卡尔曼滤波(MVC-EKF),并与传统扩展卡尔曼滤波(EKF)进行对比。代码通过一维非线性运动模型仿真,展示了MVC-EKF在处理含异常值观测数据时的鲁棒性优势,适用于目标跟踪、导航定位等状态估计场景。订阅专栏后,可直接查…

使用Docker安装MySQL和Nginx

在 Docker 中安装 MySQL 和 Nginx 非常简单&#xff0c;只需使用 docker run 命令即可快速部署。以下是详细步骤&#xff1a; 1. 安装 MySQL &#xff08;1&#xff09;拉取 MySQL 镜像 docker pull mysql:8.0 # 推荐使用 8.0 或 5.7 版本&#xff08;2&#xff09;运行 MyS…

线上活动丨主动式语音 AI:全双工、对话轮次管理、VAD 技术交流会丨RTE Meetup

一同探索语音驱动的下一代人机交互界面&#xff0c;voice agent builder 的小规模深度交流会。 当用户走在街上时&#xff0c;AI 可以主动提醒他们注意未察觉的来车或骑行者&#xff0c;甚至推荐附近不为人知的特色咖啡馆。 同样&#xff0c;如果系统检测到用户持续表达消极情绪…

如何用内网穿透远程访问Everything?实现随时随地快速检索文件

Everything 是一款高效的文件搜索工具&#xff0c;但默认仅支持局域网内使用。使用 花生壳&#xff08;内网穿透&#xff09;&#xff0c;我们可以实现远程访问Everything&#xff0c;在外网也能快速检索和管理本地文件。 本教程将详细介绍如何配置花生壳映射&#xff0c;并设…

Docker 入门教程(六):联合文件系统(UnionFS)

文章目录 &#x1f433; Docker 入门教程&#xff08;六&#xff09;&#xff1a;联合文件系统&#xff08;UnionFS&#xff09;一、联合文件系统&#xff08;UnionFS&#xff09;二、Docker 镜像的层级结构三、写层&#xff08;Copy-on-Write&#xff09;四、镜像构建缓存机制…

SQL在一个表中所有列查询某个值

使用场景&#xff1a;知道表名&#xff0c;同时知道这个表中含有某个字符串&#xff0c;但是不知道这个字符串是在表的哪些列&#xff0c;在列比较多的情况下&#xff0c;查询很麻烦&#xff0c;通过以下语句或者封装的存储可以查出字符串在哪些列出现。结果集里 ContainsValue…

【Outline】纯Docker部署指南

本文介绍了使用Docker部署Outline知识管理系统的完整流程。 主要内容包括&#xff1a; 部署PostgreSQL 12数据库并创建用户&#xff1b;安装Redis 6缓存服务&#xff1b;配置Minio对象存储服务替代AWS S3&#xff1b;搭建SSO单点登录服务器&#xff1b;准备Outline容器镜像和环…

终止分区表变更操作时误删数据字典缓存导致MySQL崩溃分析

终止分区表变更操作时误删数据字典缓存导致MySQL崩溃分析 1. 问题简述 在 MySQL 中&#xff0c;当终止一个处于 committing alter table to storage engine 阶段的分区表操作时&#xff0c;InnoDB 会尝试进行回滚并清理数据字典缓存。不幸的是&#xff0c;过程中发生了误删表…

进程关系与守护进程全解析

进程关系和守护进程 进程组 每一个进程除了有一个进程ID(PID)之外还属于一个进程组。进程组是一个或者多个进程的集合&#xff0c; 一个进程组可以包含多个进程&#xff0c;每一个进程组也有一个唯一的进程组ID(PGID)&#xff0c; 并且这个PGID 类似于进程ID&#xff0c; 同样…

PyAutoGUI 测试框架

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】

Git安装避坑指南

Git高速下载 程序员面试资料大全&#xff5c;各种技术书籍等资料-1000G 一、安装前准备&#xff1a;避免环境冲突 1. 检查系统残留&#xff08;Windows&#xff09; # 检查旧版Git残留 where git where git.exe# 检查环境变量 $env:PATH -split ; | Select-String git# 清理…

MATLAB中的并行加速技术与工具

文章目录 MATLAB中的并行加速技术与工具1. 多线程计算&#xff08;隐式并行&#xff09;2. Parallel Computing Toolbox (并行计算工具箱)2.1 parfor (并行for循环)2.2 spmd (单程序多数据)2.3 parfeval (异步并行执行) 3. GPU计算4. 分布式计算 (MATLAB Parallel Server)5. 批…

GR00T N1.5 技术报告 -- Nvidia -- 2025.6.11 -- 开源

0. 前言 GR00T N1 的详细介绍 Isaac-GR00T 在6.11 进行了全面升级&#xff0c;从 N1 进化为 N1.5&#xff0c;但基本还是基于之前的架构&#xff0c;官方发布了一个技术报告&#xff0c;并更新了github库&#xff0c;之前的N1也做了独立版本 N1 N 1.5 github 技术报告 model…

SRS WebRTC 入门

什么是 SRS WebRTC? SRS (Simple Realtime Server) 是一个支持 WebRTC 流媒体的开源媒体服务器。它允许你建立基于 WebRTC 的低延迟直播和实时通信应用。 快速开始 1. 安装 SRS bash # 使用 Docker 快速安装 docker run --rm -it -p 1935:1935 -p 1985:1985 -p 8080:8080…

从手机随拍到标准扫描件:AI如何智能校正证件照片(Python+OpenCV)

目录 一、概述二、解决方案2.1 核心挑战&#xff1a;AI眼中的“三座大山”2.2 设计思路&#xff1a;给AI一个“智能提示”2.3 实现流程&#xff1a;四步搞定 三、代码实现3.1 依赖库3.2 代码 四、结语 一、概述 在当今的线上业务中&#xff0c;要求用户上传身份证、驾驶证等证…

基于OpenCV图像分割与PyTorch的增强图像分类方案

在图像分类任务中&#xff0c;背景噪声和复杂场景常常会对分类准确率产生负面影响。为了应对这一挑战&#xff0c;本文介绍了一种结合OpenCV图像分割与PyTorch深度学习框架的增强图像分类方案。通过先对图像进行分割提取感兴趣区域&#xff08;Region of Interest&#xff0c;R…

华为云对象存储OBS 支持安卓/iOS/鸿蒙UTS组件

华为云对象存储OBS 支持安卓/iOS/鸿蒙UTS组件 介绍使用前须知vue代码调用示例权限说明API调用说明初始化配置&#xff08;openClient&#xff09;创建桶&#xff08;createBucket&#xff09;列举桶&#xff08;listBuckets&#xff09;删除桶&#xff08;deleteBucket&#xf…

Buildroot 2025.05 中文手册【AI高质量翻译】

译文在 Github 仓库 和 Gitee 仓库 保持最新&#xff0c;其它平台发的文档可能不会与之同步。 希望能够共同维护这个 仓库的 Buildroot 手册 中文译文&#xff0c;帮助更多人真正深入学习理解&#xff0c;更好的工作、生活和创造。 关于 AI 提示词 以及 更多工具 的收集&#…

采用ArcGIS10.8.2 进行插值图绘制

一、最终成果图展示 二、软件下载 链接: 百度网盘 请输入提取码 密码:azay 三、软件安装 1、在安装之前需要关闭电脑的防火墙及杀毒软件 设置-隐私和安全性-Windows安全中心-防火墙和网络保护 2、软件解压 (1)【ArcGIS_Desktop_1082_180......】“以管理员身份运行”…

Python网安-zip文件暴力破解(仅供学习)

目录 源码在这里 需要的模块 准备一个密码本和需要破解的ZIP文件 一行一行地从密码文件中读取每个密码。 核心部分 注意&#xff0c;需要修改上段代码注释里的这段具有编码问题的代码&#xff1a; 源码在这里 https://github.com/Wist-fully/Attack/tree/cracker 需要的…