Go进阶概览 -【5.5 并发编程中的常见模式与最佳实践】

5.5 并发编程中的常见模式与最佳实践

在现代编程中,并发编程是提高程序性能和响应速度的关键技术之一。

Go语言以其轻量级的协程和强大的并发支持,成为了处理并发任务的理想选择。

本节将介绍Go语言中常见的并发编程模式,并探讨如何编写高效可靠的并发代码。

本节代码存放目录为 lesson17

生产者-消费者模式

生产者-消费者模式是一种经典的并发模式,通常用于解决生产者与消费者速度不一致的问题。

生产者负责生成数据,而消费者负责处理数据。通过引入缓冲区(通常使用 channel),生产者和消费者可以并发工作,而无需相互等待。

实现代码如下所示:

func producer(ch chan<- int, wg *sync.WaitGroup) {defer wg.Done()for i := 0; i < 10; i++ {ch <- ifmt.Println("Produced: ", i)time.Sleep(time.Duration(1) * time.Second)}close(ch)
}func consumer(ch <-chan int, wg *sync.WaitGroup) {defer wg.Done()for item := range ch {fmt.Println("Consumed: ", item)}
}func main() {var (wg sync.WaitGroup)ch := make(chan int, 5)wg.Add(2)go producer(ch, &wg)go consumer(ch, &wg)wg.Wait()
}

使用注意点

  • 使用close关闭channel,防止消费者在无数据可读时死锁。

  • 使用缓冲通道提高生产者和消费者之间的处理效率。


工作池模式

工作池模式用于在处理大量任务时,限制同时执行的任务数量。

通过固定数量的Goroutine(工人),我们可以高效地处理大量任务,同时控制资源的使用。

实现代码如下所示:

func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {defer wg.Done()for j := range jobs {fmt.Printf("Worker %d started job %d\n", id, j)time.Sleep(time.Second)fmt.Printf("Worker %d finished job %d\n", id, j)results <- j * 2}
}func main() {var (wg sync.WaitGroup)jobs := make(chan int, 100)results := make(chan int, 100)for w := 1; w <= 3; w++ {wg.Add(1)go worker(w, jobs, results, &wg)}for j := 1; j <= 9; j++ {jobs <- j}close(jobs)wg.Wait()close(results)for r := range results {fmt.Println("Result: ", r)}
}

使用注意点

  • 设置适当的Worker数量以平衡资源使用和任务处理速度。

  • 使用sync.WaitGroup确保所有任务完成后程序再退出。


扇入扇出模式

扇入扇出模式常用于将多个输入源的结果汇总到一起,或将单个任务分解为多个并发子任务来处理,然后将结果汇总。

实现代码如下所示:

func process(id int, ch chan<- int) {defer close(ch)result := id * 2fmt.Printf("Process %d done\n", id)ch <- result
}func fanIn(channels ...<-chan int) <-chan int {out := make(chan int)var (wg sync.WaitGroup)wg.Add(len(channels))for _, ch := range channels {go func(c <-chan int) {defer wg.Done()for val := range c {out <- val}}(ch)}go func() {wg.Wait()close(out) // 确保所有 Goroutine 处理完毕后关闭输出通道}()return out
}func main() {channels := make([]chan int, 3)for i := range channels {channels[i] = make(chan int)go process(i+1, channels[i])}resultCh := fanIn(channels[0], channels[1], channels[2])for result := range resultCh {fmt.Println("Received:", result)}
}

使用注意点

  • 确保所有输入channel都被关闭,防止数据泄漏或死锁。

  • 使用扇入机制简化结果的汇总和处理。


超时与取消

在并发编程中,处理任务超时和取消非常重要,尤其是当某些任务可能无法在合理的时间内完成时。

实现代码如下所示:

func worker(ctx context.Context, id int, ch chan<- int) {select {case <-time.After(4 * time.Second):ch <- id * 2case <-ctx.Done():fmt.Printf("Worker %d canceled\n", id)}
}func main() {ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)defer cancel()ch := make(chan int)for i := 1; i <= 5; i++ {go worker(ctx, i, ch)}for i := 1; i <= 5; i++ {select {case res := <-ch:fmt.Println("Received: ", res)case <-ctx.Done():fmt.Println("Main canceled")return}}
}

使用注意点

  • 使用context包来处理超时和取消任务。

  • 确保Goroutine在取消时能够正确释放资源,防止资源泄漏。

总结

Go语言提供了丰富的并发编程支持,合理使用这些并发模式可以大大提升程序的性能和可维护性。

在实际开发中,应根据具体场景选择合适的并发模式,并结合Go语言的特性和最佳实践,编写高效可靠的并发代码。


我的GitHub:https://github.com/swxctx

书籍地址:https://d.golang.website/

书籍代码:https://github.com/YouCanGolang/GoDeeperCode

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习-从零基础快速入门到项目实践,这本书上市了!!!

此书地址&#xff1a; 《【2024新书】深度学习 从零基础快速入门到项目实践 文青山 跟我一起学人工智能 机器学习算法原理代码实现教程 深度学习项目分析 深度学习 从零基础快速入门到项目实践》【摘要 书评 试读】- 京东图书 除深度学习外我还写了一本软件测试书。我大概是国…

高效编程的利器 Jupyter Notebook

目录 前言1. Jupyter Notebook简介1.1 功能特点1.2 使用场景 2. 不同编程工具的对比与效率提升2.1 VS Code&#xff1a;灵活且轻量的代码编辑器2.2 PyCharm&#xff1a;面向专业开发者的集成开发环境2.3 Git&#xff1a;高效协作的版本控制工具2.4 Jupyter Notebook 和 VS Code…

idea中.git文件夹存在但是没有git功能列表

1.问题&#xff1a; 该项目中已经将.git文件夹置入了&#xff0c;但是idea中却没有git相关的功能列表&#xff0c;如图&#xff1a; 2.解决办法&#xff1a; 在【文件】-【设置】-【版本控制】-【目录映射】中添加目录映射应用就好了 &#xff08;【File】 -> 【S…

使用 Elasticsearch Reindex API 迁移数据

使用 Elasticsearch Reindex API 迁移数据 在 Elasticsearch 中&#xff0c;随着需求的变化&#xff0c;可能需要对索引进行重建或更新。这通常涉及创建新索引、迁移数据等步骤。本文介绍如何使用 Reindex API 将旧索引中的数据迁移到新索引中 一、步骤概述 创建新索引&#…

LEAN 赋型唯一性(Unique Typing)之 并行 κ 简化 (Parallel κ reduction)>>ₖ

基于 κ 简化 &#xff08;κ reduction&#xff09; 的概念&#xff0c;引入了并行简化&#xff08;Parallel Reduction&#xff09;的概念&#xff0c;记 >>&#xff0c;而 并行K简化&#xff08;Parallel K Reduction&#xff09;记为 >>ₖ 。直观的意思是&…

Windows下利用MSYS2和VS的nmake编译nginx源码

目录 一、使用说明 二、安装软件 2.1 下载依赖库 2.3 下载并安装 StrawberryPerl 2.4 下载并安装 MSYS 2 2.5 nginx源代码下载 三、编译配置 3.1 设置NGX_MSVC_VER 3.2 配置 Makefile 3.3 编译代码 3.4 整理Nginx发布环境 四、错误处理 一、使用说明 本文章主要记…

【正点原子K210连载】第四十章 YOLO2人手检测实验摘自【正点原子】DNK210使用指南-CanMV版指南

第四十章 YOLO2人手检测实验 在上一章节中&#xff0c;介绍了利用maix.KPU模块实现YOLO2的人脸检测&#xff0c;本章将继续介绍利用maix.KPU模块实现YOLO2的人手检测。通过本章的学习&#xff0c;读者将学习到YOLO2网络的人手检测应用在CanMV上的实现。 本章分为如下几个小节&…

RocketMQ核心编程模型与最佳实践

目录 一、RocketMQ的消息模型 1、RocketMQ客户端基本流程 2、消息确认机制 3、广播消息 4、顺序消息机制 5、延迟消息 6、批量消息 7、过滤消息 8、事务消息 9、ACL权限控制机制 二、SpringBoot整合RocketMQ 1、快速实战 2、如何处理各种消息类型 3、实现原理 三…

周末愉快!——周复盘

加班的晚上有一个美梦&#xff01; 周末愉快简单复盘结尾 精华&#xff1a; 在这个信息爆炸的时代&#xff0c;我们的大脑每天都被无数的数据和刺激充斥&#xff0c;以至于我们常常感到应接不暇。然而&#xff0c;正如古人所言&#xff1a;“不飞则已&#xff0c;一飞冲天”&am…

GraphRAG 与 RAG 的比较分析

检索增强生成&#xff08;RAG&#xff09;技术概述 检索增强生成&#xff08;Retrieval-Augmented Generation&#xff0c;简称 RAG&#xff09;是一种旨在提升大型语言模型&#xff08;Large Language Models&#xff0c;LLMs&#xff09;性能的技术方法。其核心思想是通过整…

容器化安装Jenkins部署devops

基础环境介绍 系统使用的是centos7.9 内核使用的是5.16.13-1.el7.elrepo.x86_64 容器使用的是26.1.4 docker-compose使用的是 v2.29.0 链路图 devops 配置git环境插件 部署好jenkins后开始配置 jenkins连接git&#xff0c;这里需要jenkins有连接git的插件。在已安装的插件…

豆包Python SDK接入流程

模型与价格 豆包的模型介绍可以看豆包大模型介绍&#xff0c;模型价格可以看豆包定价文档里的“模型推理” - “大语言模型” - “字节跳动”部分。 推荐使用以下模型&#xff1a; Doubao-lite-32k&#xff1a;每百万 token 的输入价格为 0.3 元&#xff0c;输出价格为 0.6 元…

Hexo博客私有部署Twikoo评论系统并迁移评论记录(自定义邮件回复模板)

部署 之前一直使用的artalk&#xff0c;现在想改用Twikoo&#xff0c;采用私有部署的方式。 私有部署 (Docker) 端口可以根据实际情况进行修改 docker run --name twikoo -e TWIKOO_THROTTLE1000 -p 8100:8100 -v ${PWD}/data:/app/data -e TWIKOO_PORT8100 -d imaegoo/twi…

LabVIEW编程能力如何能突飞猛进

要想让LabVIEW编程能力实现突飞猛进&#xff0c;需要采取系统化的学习方法&#xff0c;并结合实际项目进行不断的实践。以下是一些提高LabVIEW编程能力的关键策略&#xff1a; 1. 扎实掌握基础 LabVIEW的编程本质与其他编程语言不同&#xff0c;它是基于图形化的编程方式&…

nethogs显示每个进程所使用的带宽

1、安装nethogs&#xff1a; Ubuntu、Debian和Fedora用户可以从默认软件库获得。CentOS用户则需要Epel。 #ubuntu或debian安装方法 sudo apt-get install nethogs #fedroa或centos安装法 sudo yum install nethogs -y 2、使用测试 nethogs是一款小巧的"net top&quo…

开源项目还需要花钱吗

开源和免费并不完全等同&#xff0c;很多用户对开源软件是否真的不花钱存在误解。本文深入探讨开源的真正含义、开源项目是否需要付费、以及开源软件的盈利模式。通过分析国内外主流开源平台&#xff0c;我们将帮助读者更好地理解开源与免费之间的区别。 什么是开源 开源软件指…

增强现实系列—GaussianAvatars: Photorealistic Head Avatar

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

【ollama】ollama配置本地大模型并运行

ollama的Github链接 https://github.com/ollama/ollamaollama官网链接 https://ollama.com/打开后点击下载 下载完成后进行安装&#xff0c;安装完毕后在终端输入以下&#xff0c;代表安装成功 ollama在ollama官网的模型库中找到需要的模型&#xff0c;这里使用阿里最新开源…

ZYNQ FPGA自学笔记~操作PLL

一 时钟缓冲器、管理和路由 垂直时钟中心&#xff08;clock backbone&#xff09;将设备分为相邻的左侧和右侧区域&#xff0c;水平中心线将设备分为顶部和底部两侧。clock backbone中的资源镜像到水平相邻区域的两侧&#xff0c;从而将某些时钟资源扩展到水平相邻区域。BUFG不…

JavaWeb---三层架构

文章目录 1. 为什么需要分层&#xff1f;2.软件设计中的分层模式3.分层4.三层架构&#xff1a;显示层、业务逻辑层、数据访问层3. 案例&#xff1a;利用三层架构原理实现编写web程序的流程 摘自&#xff1a;https://blog.csdn.net/qq_64001795/article/details/124112824 1. 为…