Go进阶高并发(多线程)处理教程

Go进阶高并发处理教程

目录

  1. Go并发编程基础
  2. Goroutine深入理解
  3. 同步原语详解
  4. 并发模式与最佳实践
  5. 性能优化技巧
  6. 实战案例

Go并发编程基础

什么是并发?

并发是指程序能够同时处理多个任务的能力。Go语言从设计之初就将并发作为核心特性,提供了简洁而强大的并发编程模型。

Go并发模型的优势

  • 轻量级协程:Goroutine比传统线程更轻量
  • CSP模型:通过通信来共享内存,而不是通过共享内存来通信
  • 内置调度器:Go运行时自动管理goroutine的调度

Goroutine深入理解

创建和启动Goroutine

package mainimport ("fmt""time"
)func worker(id int) {fmt.Printf("Worker %d starting\n", id)time.Sleep(time.Second)fmt.Printf("Worker %d done\n", id)
}func main() {// 启动多个goroutinefor i := 1; i <= 5; i++ {go worker(i)}// 等待所有goroutine完成time.Sleep(2 * time.Second)fmt.Println("All workers completed")
}

Goroutine的生命周期

  1. 创建:使用go关键字创建
  2. 调度:由Go调度器管理
  3. 执行:在可用的OS线程上执行
  4. 结束:函数返回时自动结束

调度器工作原理

Go使用M:N调度模型:

  • M:OS线程(Machine)
  • P:处理器(Processor)
  • G:Goroutine
G1  G2  G3  G4\   |   |  /\  |   | /\ |   |/\|   |P1  P2|   |M1  M2

同步原语详解

sync.WaitGroup

用于等待一组goroutine完成:

package mainimport ("fmt""sync""time"
)func worker(id int, wg *sync.WaitGroup) {defer wg.Done() // 完成时调用Done()fmt.Printf("Worker %d starting\n", id)time.Sleep(time.Second)fmt.Printf("Worker %d done\n", id)
}func main() {var wg sync.WaitGroupfor i := 1; i <= 5; i++ {wg.Add(1) // 增加等待计数go worker(i, &wg)}wg.Wait() // 等待所有goroutine完成fmt.Println("All workers completed")
}

sync.Mutex

互斥锁用于保护共享资源:

package mainimport ("fmt""sync"
)type Counter struct {mu    sync.Mutexvalue int
}func (c *Counter) Increment() {c.mu.Lock()defer c.mu.Unlock()c.value++
}func (c *Counter) Value() int {c.mu.Lock()defer c.mu.Unlock()return c.value
}func main() {counter := &Counter{}var wg sync.WaitGroup// 启动100个goroutine同时增加计数器for i := 0; i < 100; i++ {wg.Add(1)go func() {defer wg.Done()for j := 0; j < 1000; j++ {counter.Increment()}}()}wg.Wait()fmt.Printf("Final counter value: %d\n", counter.Value())
}

sync.RWMutex

读写锁允许多个读操作同时进行:

type SafeMap struct {mu sync.RWMutexdata map[string]int
}func (sm *SafeMap) Get(key string) (int, bool) {sm.mu.RLock()defer sm.mu.RUnlock()val, ok := sm.data[key]return val, ok
}func (sm *SafeMap) Set(key string, value int) {sm.mu.Lock()defer sm.mu.Unlock()sm.data[key] = value
}

sync.Once

确保某个操作只执行一次:

package mainimport ("fmt""sync"
)var once sync.Once
var instance *Singletontype Singleton struct {data string
}func GetInstance() *Singleton {once.Do(func() {fmt.Println("Creating singleton instance")instance = &Singleton{data: "singleton"}})return instance
}func main() {var wg sync.WaitGroupfor i := 0; i < 10; i++ {wg.Add(1)go func(id int) {defer wg.Done()s := GetInstance()fmt.Printf("Goroutine %d got instance: %s\n", id, s.data)}(i)}wg.Wait()
}

并发模式与最佳实践

Worker Pool模式

package mainimport ("fmt""sync""time"
)type Job struct {ID   intData string
}type Result struct {Job    JobOutput string
}func worker(id int, jobs <-chan Job, results chan<- Result, wg *sync.WaitGroup) {defer wg.Done()for job := range jobs {fmt.Printf("Worker %d processing job %d\n", id, job.ID)time.Sleep(time.Millisecond * 100) // 模拟工作result := Result{Job:    job,Output: fmt.Sprintf("Processed by worker %d", id),}results <- result}
}func main() {const numWorkers = 3const numJobs = 10jobs := make(chan Job, numJobs)results := make(chan Result, numJobs)var wg sync.WaitGroup// 启动workerfor i := 1; i <= numWorkers; i++ {wg.Add(1)go worker(i, jobs, results, &wg)}// 发送任务for i := 1; i <= numJobs; i++ {jobs <- Job{ID: i, Data: fmt.Sprintf("data-%d", i)}}close(jobs)// 等待所有worker完成go func() {wg.Wait()close(results)}()// 收集结果for result := range results {fmt.Printf("Job %d result: %s\n", result.Job.ID, result.Output)}
}

扇入扇出模式

// 扇出:将工作分发给多个goroutine
func fanOut(input <-chan int, workers int) []<-chan int {outputs := make([]<-chan int, workers)for i := 0; i < workers; i++ {output := make(chan int)outputs[i] = outputgo func(out chan<- int) {defer close(out)for n := range input {out <- n * n // 计算平方}}(output)}return outputs
}// 扇入:将多个channel的结果合并
func fanIn(inputs ...<-chan int) <-chan int {output := make(chan int)var wg sync.WaitGroupfor _, input := range inputs {wg.Add(1)go func(in <-chan int) {defer wg.Done()for n := range in {output <- n}}(input)}go func() {wg.Wait()close(output)}()return output
}

性能优化技巧

1. 合理设置GOMAXPROCS

import "runtime"func init() {// 设置使用的CPU核心数runtime.GOMAXPROCS(runtime.NumCPU())
}

2. 避免goroutine泄漏

// 错误示例:可能导致goroutine泄漏
func badExample() {ch := make(chan int)go func() {ch <- 1 // 如果没有接收者,这个goroutine会永远阻塞}()// 函数返回,但goroutine仍在运行
}// 正确示例:使用context控制goroutine生命周期
func goodExample(ctx context.Context) {ch := make(chan int, 1) // 使用缓冲channelgo func() {select {case ch <- 1:case <-ctx.Done():return}}()
}

3. 使用对象池减少GC压力

import "sync"var pool = sync.Pool{New: func() interface{} {return make([]byte, 1024)},
}func processData(data []byte) {buf := pool.Get().([]byte)defer pool.Put(buf)// 使用buf处理数据
}

实战案例

并发HTTP客户端

package mainimport ("fmt""net/http""sync""time"
)type Result struct {URL        stringStatusCode intDuration   time.DurationError      error
}func fetchURL(url string, results chan<- Result, wg *sync.WaitGroup) {defer wg.Done()start := time.Now()resp, err := http.Get(url)duration := time.Since(start)result := Result{URL:      url,Duration: duration,Error:    err,}if err == nil {result.StatusCode = resp.StatusCoderesp.Body.Close()}results <- result
}func main() {urls := []string{"https://www.google.com","https://www.github.com","https://www.stackoverflow.com","https://www.golang.org",}results := make(chan Result, len(urls))var wg sync.WaitGroup// 并发请求所有URLfor _, url := range urls {wg.Add(1)go fetchURL(url, results, &wg)}// 等待所有请求完成go func() {wg.Wait()close(results)}()// 处理结果for result := range results {if result.Error != nil {fmt.Printf("Error fetching %s: %v\n", result.URL, result.Error)} else {fmt.Printf("%s: %d (%v)\n", result.URL, result.StatusCode, result.Duration)}}
}

总结

Go语言的并发编程提供了强大而简洁的工具:

  1. Goroutine:轻量级协程,易于创建和管理
  2. Channel:类型安全的通信机制
  3. sync包:提供各种同步原语
  4. 并发模式:Worker Pool、扇入扇出等经典模式

掌握这些概念和技巧,能够帮助您构建高性能、可扩展的并发应用程序。记住Go的并发哲学:通过通信来共享内存,而不是通过共享内存来通信

参考资源

  • Go官方文档 - 并发
  • Go并发模式
  • Go内存模型

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

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

相关文章

一种基于单片机控制的太阳能电池板系统设计

摘 要: 设计的太阳能电池板系统&#xff0c;以单片机单元为核心&#xff0c;集检测、光能跟踪、板面清洁、输出控制为一体&#xff0c;解决了传统太阳能板控制功能简单、效率低的技术问题&#xff0c;达到了自动监测输出电能、自动清洗板面、全方位跟踪光伏发电最大效率点的技术…

前端实现类浏览器的 Ctrl+F 全局搜索功能(Vue2 + mark.js,用于Electron 、QT等没有浏览器Ctrl+F全局搜索功能的壳子中)

&#x1f4bb; 在 Electron 中实现类浏览器的 CtrlF 全局搜索功能&#xff08;Vue2 mark.js&#xff09;本文介绍如何在 Electron 应用中构建一个像 Chrome 一样的 CtrlF 查找框&#xff0c;支持全局高亮、滚动定位、关键词计数与上下跳转。✨ 背景 在网页浏览器中&#xff0c…

详解力扣高频 SQL 50 题-1757.可回收且低脂的产品【入门】

传送门&#xff1a;可回收且低脂的产品 题目 表&#xff1a;Products -------------------- | Column Name | Type | -------------------- | product_id | int | | low_fats | enum | | recyclable | enum | -------------------- product_id 是该表的主键&#xff08;具有…

CSS3 网格元素

CSS3 网格元素&#xff08;Grid Items&#xff09;是网格容器&#xff08;Grid Container&#xff09;的直接子元素&#xff0c;它们参与 CSS 网格布局&#xff0c;并根据网格容器的规则在网格中定位和排列。以下是对网格元素的详细中文讲解&#xff0c;涵盖定义、相关属性、用…

30天打牢数模基础-决策树讲解

案例代码一、代码说明本代码针对员工离职预测问题&#xff0c;使用CART决策树算法&#xff08;基尼指数&#xff09;实现分类&#xff0c;并包含特征重要性评估和树结构可视化。数据为模拟的10个员工样本&#xff0c;特征包括工作年限、月薪、是否加班、团队氛围评分&#xff0…

React与jQuery全栈实战指南

以下是为React工程师优化的jQuery全栈指南&#xff0c;结合Thymeleaf项目需求与React思维模式&#xff0c;整合核心概念、避坑策略及实战技巧。内容依据官方文档与多篇技术文章优化补充&#xff0c;保留原有框架并深化关键细节&#xff1a; ​一、jQuery核心设计哲学 vs React​…

Redis分布式锁的学习(八)

一、分布式锁 1.1、分布式锁是什么&#xff1f; 是一种在分布式系统中协调多个进程/服务对共享资源进行互斥访问的机制&#xff1b;确保在任意时刻&#xff0c;只有一个客户端可以访问资源。 1.2、为什么需要分布式锁&#xff1f; 解决多个服务/进程对同共享资源竞争&…

spring的常用注解汇总

在 Spring 和 Spring Boot 框架中&#xff0c;有许多核心注解被广泛应用。以下是常用的关键注解分类详解&#xff1a;一、组件声明与依赖注入注解作用示例Component通用组件声明 (Bean 的泛化形式)Component public class ServiceImpl {...}Service标记服务层&#xff08;业务逻…

Claude4、GPT4、Kimi K2、Gemini2.5、DeepSeek R1、Code Llama等2025主流AI编程大模型多维度对比分析报告

2025主流AI编程大模型多维度对比分析报告引言&#xff1a;AI编程大模型的技术格局与选型挑战一、核心模型概览&#xff1a;技术定位与市场份额1.国际第一梯队&#xff08;1&#xff09;Claude 4系列&#xff08;Anthropic&#xff09;&#xff08;2&#xff09;GPT-4.1&#xf…

Overleaf中下载.aux和.bbl文件

有些会议提交终稿的时候&#xff0c;可能会让上传.bbl和.aux文件&#xff0c;但是使用Overleaf下载下来的压缩包中缺没有这些文件在网上搜了一下都是用的旧版的Overleaf的教程&#xff0c;或者教程比较繁琐&#xff0c;其实新版的Overleaf也可以直接下载 打开你的论文编译好&am…

uniapp写app做测试手机通知栏展示内容

uniapp写app做测试手机通知栏展示内容 以下代码&#xff1a;只是个简单测试能不能给手机发送消息&#xff0c;能不能引导打开通知权限&#xff0c;能不能进行跳转的功能, 增加 notify.js 以下文件 // 模拟本地通知功能 export function showNotification() {// 1. 检查通知…

分布式云计算:未来计算架构的全新演进

随着信息技术的不断发展,尤其是云计算技术的飞速进步,企业和个人对计算资源的需求已经从传统的单一数据中心向更为灵活、可扩展的分布式架构转变。分布式云计算作为一种新兴的云计算模型,旨在将计算资源和数据存储分布在多个地理位置上,从而提供更加高效、安全和可靠的服务…

2025年海外短剧独立站开发:H5+PC端双平台技术实践与增长策略

引言在全球化内容消费浪潮下&#xff0c;海外短剧市场正经历爆发式增长。据DataEye《2025H1海外微短剧行业数据报告》显示&#xff0c;2025年海外短剧市场规模预计突破45亿美元&#xff0c;其中东南亚、拉美等新兴市场贡献超30%增量。本文将以某头部短剧平台的双平台开发实践为…

OpenAI发布ChatGPT Agent,AI智能体迎来关键变革

注&#xff1a;此文章内容均节选自充电了么创始人&#xff0c;CEO兼CTO陈敬雷老师的新书《GPT多模态大模型与AI Agent智能体》&#xff08;跟我一起学人工智能&#xff09;【陈敬雷编著】【清华大学出版社】 清华《GPT多模态大模型与AI Agent智能体》书籍配套视频课程【陈敬雷…

企业级安全威胁检测与响应(EDR/XDR)架构设计

在这个网络威胁如洪水猛兽的时代&#xff0c;企业的安全防护不能再像守城门的老大爷一样只会喊"什么人&#xff1f;口令&#xff01;"了。我们需要的是一套像FBI一样具备全方位侦察能力的智能防护系统。 &#x1f4cb; 文章目录 1. 什么是EDR/XDR&#xff1f;别被这…

Stream流-Java

Stream流的作用&#xff1a;结合了Lambda表达式&#xff0c;简化集合&#xff0c;数组的操作Stream流的使用步骤&#xff1a;1. 先得到一条Stream流&#xff08;流水线&#xff09;&#xff0c;并把数据放上去获取方式方法名说明单列集合default Stream<E> stream()Colle…

Leetcode 327. 区间和的个数

1.题目基本信息 1.1.题目描述 给你一个整数数组 nums 以及两个整数 lower 和 upper 。求数组中&#xff0c;值位于范围 [lower, upper] &#xff08;包含 lower 和 upper&#xff09;之内的 区间和的个数 。 区间和 S(i, j) 表示在 nums 中&#xff0c;位置从 i 到 j 的元素…

MinIO 版本管理实践指南(附完整 Go 示例)

✨ 前言 在构建企业级对象存储系统时,“对象的版本管理”是一个关键特性。MinIO 作为一款高性能、Kubernetes 原生的 S3 兼容对象存储系统,也支持强大的版本控制功能。 本文将通过 Go 示例代码 + 实操讲解 的形式,手把手带你掌握 MinIO 的版本控制能力,包括开启版本控制、…

数组toString方法及类型检测修复方案

在 JavaScript 中&#xff0c;数组的 toString() 方法被覆盖&#xff08;重写&#xff09;为返回数组元素的逗号分隔字符串&#xff0c;而不是原始的 [object Array] 类型标识。以下是详细解释和修复方案&#xff1a;问题原因Array.prototype.toString 被覆盖数组继承自 Object…