首页 > 其他分享 >go的并发梳理

go的并发梳理

时间:2024-01-13 09:01:23浏览次数:27  
标签:WaitGroup goroutine Golang 并发 context go Go 梳理

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

原创 俞凡 DeepNoMind DeepNoMind 2024-01-06 13:10 发表于上海 3人听过

并发性支持是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

 感恩有你,一路同行 

赞赏二维码喜欢作者

Golang27 Golang · 目录 上一篇Golang数据结构性能优化实践下一篇Go、容器以及Linux调度器 阅读原文 阅读 922 DeepNoMind ​ 喜欢此内容的人还喜欢   Go事件管理器:简单实现     我看过的号 DeepNoMind 不看的原因   领先的数据集成平台开源!     开源好项目 不看的原因   Go语言生成PDF文件指南     苜蓿草科技 不看的原因   关注公众号后可以给作者发消息              

人划线

 

标签:WaitGroup,goroutine,Golang,并发,context,go,Go,梳理
From: https://www.cnblogs.com/cheyunhua/p/17961934

相关文章

  • golang进程(主线程)与协程
    概念主线程:golang中的主线程(在go中主线程就是进程,相比与其他编程语言叫法不一样)协程:golang中协程是轻量级的线程(相比于其他语言,只有进程和线程);python中有进程和线程的概念,也有协程的概念;python中的协程通过async来实现并发与并行的概念并发:在一个cpu上有10个线程,每个线程10......
  • 一个脚本打包三个平台的linux,mac,windows的golang程序
    一个脚本打包三个平台的linux,mac,windows的golang程序:#!/bin/bash#设置变量APP_NAME="atmp"VERSION="1.0.0"BUILD_TIME=$(date+%Y-%m-%d_%H:%M:%S)BUILD_DIR="bin"PLATFORMS=("linux/amd64""windows/amd64""darwin/amd64&......
  • mac下golang打包到Linux上执行报错:No such file or directory
    本地mac打包golang二进制文件到linux服务器报错:-bash:./atmp-linux:Nosuchfileordirectory很奇怪,明明可执行文件在当前目录下,为什么会找不到呢?使用列出动态库依赖的lld(listdynamicdependencies)命令查看了下,发现:lddatmp-linux发现报错:./atmp-linux:errorwhile......
  • 精确掌控并发:分布式环境下并发流量控制的设计与实现(一)
    这是《百图解码支付系统设计与实现》专栏系列文章中的第(10)篇。点击上方关注,深入了解支付系统的方方面面。本篇主要讲清楚常用的并发流量控制方案,包括固定窗口、滑动窗口、漏桶、令牌桶、分布式消息中间件等,以及各种方案在支付系统不同场景下的应用。在非支付场景,也常常需要用到这些......
  • 深度解析Java中的ReadWriteLock:高效处理并发读写操作
    第1章:引言大家好,我是小黑,今天咱们聊聊读写锁。当多个线程同时对同一数据进行读写操作时,如果没有合理的管理,那数据就乱套了。就好比小黑在写日记,突然来了一帮朋友,大家都想往日记本上写点什么,不加以控制,日记本就成了涂鸦板。这时,ReadWriteLock就派上用场了。它可以确保当一个线程......
  • Spring学习记录之GoF之代理模式
    Spring学习记录之GoF之代理模式前言这篇文章是我第二次学习b站老杜的spring相关课程所进行的学习记录,算是对课程内容及笔记的二次整理,以自己的理解方式进行二次记录,其中理解可能存在错误,欢迎且接受各位大佬们的批评指正;关于本笔记,只是我对于相关知识遗忘时快速查阅了解使用,至......
  • Top-N推荐算法 Top-N recommendation Algorithms
    引言推荐算法是计算机专业中的一种算法,通过一些计算,能够推测用户喜欢的东西,在互联网环境中应用比较广泛。Top-N算法在生活中非常常见,比如学术论文推荐论文、音乐软件推荐歌曲等。今天看到一篇名叫"ARevisitingStudyofAppropriateOfflineEvaluationforTop-NRecommendati......
  • 如何在脚本中使用导入django环境?
    importosif__name__=='__main__':os.environ.setdefault('DJANGO_SETTINGS_MODULE','dd85.settings')#这句直接去wsgi.py中拷贝过来即可importdjangodjango.setup()fromapp03importmodelsstudent_list=models.Stude......
  • Go+Gin+xorm+MySql实现增删改查
    一、概述承接上一篇(ps:原生增删改查),本篇使用xorm实现增删改查。之所以要使用xrom是因为xrom可以极大的缩小操作数据库的成本。使用rom之前需要导入响应的包gogetgithub.com/go-xorm/xorm#安装xormgogetxorm.io/coregoget-ugithub.com/go-sql-driver/mys......
  • Argo-rollout使用--蓝绿和金丝雀发布
    1.安装argo-rolloutkubectlcreatenamespaceargo-rolloutskubectlapply-nargo-rollouts-fhttps://github.com/argoproj/argo-rollouts/releases/download/v1.5.0/install.yaml官网:https://argoproj.github.io/argo-rollouts/ 2.蓝绿部署部署applicationapiVersion......