首页 > 其他分享 >Golang不可不知的7个并发概念

Golang不可不知的7个并发概念

时间:2024-01-31 09:37:19浏览次数:32  
标签:WaitGroup 概念 goroutine Golang 并发 context Go

Golang不可不知的7个并发概念

原创 俞凡 DeepNoMind DeepNoMind 2024-01-13 11:08 发表于上海 听全文

并发性支持是Golang最重要的原生特性之一,本文介绍了Golang中和并发性相关的7个概念。原文: Golang: 7 must-know concurrency related concepts[1]

并发是Go编程语言的基本特性,意味着程序可以同时执行多个任务。Golang的并发独特而强大,其内置的轻量级协程(goroutine)和通道(channel)支持创建可伸缩、安全、高性能的高并发系统。

图片

本文将探索Go中和并发性有关的七个有趣事实,并提供示例。

1. 协程(Goroutines)

Goroutine是Go编程语言的特性之一,这是轻量级线程,与同一地址空间中的其他goroutine并发运行。它的创建成本非常低,Go运行时可以同时处理数千个goroutine。Goroutine使编写高并发程序变得容易,这些程序可以根据需要伸缩。

下面是一个创建goroutine的例子:

图片

在本例中,定义了printMessage函数,该函数接受一个消息字符串以及打印消息的次数,其中sleep语句用来模拟在每次消息打印之间完成的一些额外工作。

main函数中,调用go printMessage("Hello", 5)go printMessage("world", 5)来启动两个goroutine。这创建了两个与主线程并发运行的独立执行线程。time.Sleep(1 * time.Second)语句用于将主线程暂停一秒钟,这给了两个goroutine足够的时间来执行和打印消息。

2. 通道(Channels)

Channel是Go的另一个基本特性,支持在程序之间进行通信和同步。Channel是一种有类型管道,可以使用<-操作符发送和接收。Channel确保了并发进程之间安全有效的通信。

下面是一个使用channel的例子:

图片

在本例中,make函数创建了一个string类型的channel。然后,我们创建一个使用<-操作符向channel发送消息"Hello from channel!"的goroutine。最后,我们使用<-操作符从channel接收消息并将其打印到控制台。

3. 缓冲通道(Buffered Channels)

缓冲通道是在读取之前可以保存一定数量的值的通道,对于管理并发系统中的突发流量非常有用。使用make函数可以创建缓冲通道,通过第二个参数指定缓冲区大小。

下面是一个使用缓冲通道的例子:

图片

在本例中,我们创建了一个缓冲区大小为2的int类型的缓冲通道。然后使用<-操作符向通道发送两个值(12)。最后,我们使用<-操作符从通道接收值,并打印到控制台。

4. Select语句

Go中的select语句允许我们同时等待多个通道操作。这是个强大的结构,可以帮助我们编排复杂的并发系统。select语句会阻塞直到其中一个case可以继续进行,此时就执行该case。

下面是一个使用select语句的例子:

图片

本例中创建了两个通道(ch1ch2)和两个向这些通道发送消息的goroutine。然后,我们使用select语句等待消息到达ch1ch2。当消息到达时,将其打印到控制台。

5. Mutex

Go中的互斥锁(sync.Mutex)提供了一种简单有效的方法来保护共享资源免受并发访问。mutex是一种互斥锁,一次只允许一个程序访问资源,任何其他试图在资源被锁定时访问该资源的goroutine都将被阻塞,直到锁被释放。

下面是一个使用互斥锁的例子:

图片

在这个例子中,我们定义了一个Counter类型,包含count字段和一个sync.Mutex。在Counter类型上定义了两个方法: Increment()Count()。这两种方法都使用互斥锁来确保一次只有一个goroutine可以访问count字段。最后,我们创建1000个增加count字段的goroutine,在打印最终计数之前等待它们全部完成。

6. WaitGroup

Go中的sync.WaitGroup类型提供了一种同步多个goroutine的简单方法。WaitGroup在继续之前等待一组goroutine完成,是协调多个goroutine执行的有力工具,可以帮助我们确保在进入程序的下一步之前,所有goroutine都已完成。

下面是一个使用WaitGroup的例子:

图片

在本例中,我们创建了一个WaitGroup和10个goroutine。每个goroutine休眠数秒,然后向控制台打印一条消息。我们使用WaitGroup来确保在打印最终消息之前所有的goroutine都已经完成。

7. Context

Go中的context包提供了一种跨API边界和进程之间携带截止日期、取消信号和其他请求作用域值的方法,是在并发系统中管理资源的强大工具,可以帮助我们避免常见问题(如goroutine泄漏)。

下面是一个使用context的例子:

func worker(ctx Context.context, wg *sync.WaitGroup) {
  defer wg.Done()
  for {
    select {
    case <- ctx.Done():
      fmt.Println("Worker received cancel signal")
      return
    default:
      fmt.Println("Worker is working...")
      time.Sleep(1 * time.Second)
    }
  }
}

func main() {
  ctx, cancel := context.WithCancel()
  var wg sync.WaitGroup
  wg.Add(1)
  go worker(ctx, &wg)
  time.Sleep(5 * time.Second)
  cancel()
  wg.Wait()
  fmt.Println("All workers stopped")
}

在这个例子中,我们定义了一个接受context.Contextsync.WaitGroup作为参数的worker函数。worker函数用select语句等待来自context的cancel信号或者在default中执行某些工作。我们还定义了一个main函数,该函数用context.WithCancel创建上下文,并启动worker goroutine。等待5秒后cancel context,它会向worker goroutine发送cancel信号,让它停止工作。在打印最终消息之前,我们用WaitGroup来等待worker goroutine结束。

结论

总的来说,并发性是Go中的一个重要主题,并且该语言为处理并发系统提供了一组强大的工具。无论是构建web服务器、分布式系统还是简单的命令行工具,了解Go的并发性对于构建健壮、可扩展、高效的程序都必不可少。


你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!

参考资料

[1]

Golang: 7 must-know concurrency related concepts: https://levelup.gitconnected.com/7-interesting-concurrency-related-concepts-in-golang-ea09a8644e6a

- END -

 

俞凡 DeepNoMind

 感恩有你,一路同行 

赞赏二维码钟意作者

Golang47 Golang · 目录 上一篇从错误中学习: 了解Go编程的6个坏习惯下一篇基于FX构建大型Golang应用 阅读原文 阅读 162 DeepNoMind ​ 喜欢此内容的人还喜欢   Go事件管理器:简单实现     我看过的号 DeepNoMind 不看的原因   由汇编到Golang,深入浅出Golang Runtime 理解 Goroutine 调度模型 GMP     社恐的小马同学 不看的原因   掌握sync包:并发安全的Go语言秘籍     GO语言入门之路 不看的原因   关注公众号后可以给作者发消息              

人划线

 

标签:WaitGroup,概念,goroutine,Golang,并发,context,Go
From: https://www.cnblogs.com/cheyunhua/p/17998533

相关文章

  • nginx-go-crossplane crossplane golang 版本的nginx 配置解析包
    nginx-go-crossplane属于python版本crossplanenginx配置解析包的golang移植可以实现nginx配置解析转换为json格式的数据,当然也支持将json转换为nginx配置格式说明对于希望基于nginx搞自己的流量统一平台,同时希望基于api管理的,nginx-go-crossplane是一个很不错的选择......
  • 基于fx构建大型golang应用
    基于FX构建大型Golang应用原创 俞凡DeepNoMind DeepNoMind 2023-12-2313:29 发表于上海 1人听过Uber开源的FX可以帮助Go应用解耦依赖,实现更好的代码复用。原文: HowtobuildlargeGolangapplicationsusingFX[1]构建复杂的Go应用程序可能会引入很多耦合Go......
  • 在K8S中,Pod亲和性概念是什么?
    在Kubernetes(简称K8S)中,Pod亲和性和反亲和性(AffinityandAnti-Affinity)是集群调度策略的重要组成部分,它们用于控制Pod如何与节点或其他Pod相对应地放置或避免放置在一起。Pod亲和性(Affinity):Pod亲和性允许用户指定某种规则,使得Pod更倾向于被调度到满足特定条件的节点上运行,或者与......
  • 数据挖掘概念与技术 - chapter 2 - 认识数据
    数据特性:均值中位数众数中心趋势度量这些基本统计量有助于数据预处理时填补空缺值、光滑噪声、识别离群点。考察数据对象的"相似性/相异性"可以用于检测最近邻分类数据对象:一个实体(样本实例数据点)属性:一个数据字段特征变量维度单变量双变量标称属性:与名称相关,......
  • 上个厕所的时间了解链路追踪基本概念
    大家好,我是蓝胖子,随着微服务的普及,在面对日益复杂的架构和请求链路时,链路追踪技术就显得更加重要,今天我们花5分钟的时间,来掌握和链路追踪相关的基本概念。不会涉及到具体的技术框架和落地,本文主要是对链路追踪中涉及的专业术语做一个简短的介绍。不同链路追踪的SDK可能对相关的......
  • 软件测试学习笔记丨JMeter_实现分组并发
    Jmeter_实现分组并发实现思路:线程数和时间进行参数化,使用命令模式进行执行,再添加报告进行每次展示。执行时可以使用linux定时器或者脚本调用。命令执行命令启动jmeter命令:jmeter-Jpara1=4-Jpara2=15-n-tpreClassMenu_1117.jmx-le:/res/res1.jtl-e-oe:/res/res/......
  • Java并发基础:一文讲清util.concurrent包的作用
    java.util.concurrent包是Java中用于并发编程的重要工具集,提供了线程池、原子变量、并发集合、同步工具类、阻塞队列等一系列高级并发工具类,使用这些工具类可以极大地简化并发编程的难度,减少出错的可能性,提高程序的效率和可维护性。官方文档地址:https://docx.iamqiang.com/jd......
  • Powershell 并发任务 | Runspace 线程 | 结果获取
    介绍在PowerShell中进行多任务处理(Multithreading或ParallelProcessing)主要目的是提高脚本的执行效率和性能。对于需要处理大量数据或执行多个独立任务的脚本来说尤其有用。提高性能:多任务处理允许脚本同时执行多个任务,从而加快整体执行速度。对于需要处理大型数据集或执......
  • 漫画图解 Go 并发编程之:Channel
    当谈到并发时,许多编程语言都采用共享内存/状态模型。然而,Go通过实现CommunicatingSequentialProcesses(CSP)而与众不同。在CSP中,程序由不共享状态的并行处理器组成;相反,他们使用Channel来沟通和同步他们的行动。因此,对于有兴趣采用Go的开发人员来说,理解Channel的工作原理......
  • 使用Golang实现ping检测主机在线的功能
    使用"github.com/go-ping/ping"这个第三方库可以非常简单的实现ping功能packagemainimport("fmt""os""time""github.com/go-ping/ping")funcCheckHostOnline(ipaddrstring)bool{pinger,err:=ping.N......