golang 协程并发代码 demo

简介: golang 协程并发代码 demo

有时我们可能想既在外层循环中实现多协程并发,还想在内层循环中实现多协程并发,那么我们需要同时在内层和外层使用 WaitGroup() 来控制主协程不退出。

下面是一个 demo:

博客平台纯手敲,可能存在字符拼写错误

import (
  "fmt"
  "sync"  
)
func handleTask() {
  demoList := []string{"123", "456", "abc", "ddd"}
  var wg = sync.WaitGroup{}
  for idx, item := range demoList {
    // 每个元素创建一个新协程去处理
    wg.Add(1) // 
    go func(idx int){
      defer wg.Done() // 协程退出前将 wg 计数器减一,否则最后计数器无法减为0,会一直卡在 wg.wait() 那一行
      // 内部还想新建子协程去做不同的事,减少执行时间
      var innerWg = sync.WaitGroup{} // 
      innerWg.Add(1)
      go func(){
        defer innerWg.Done() // 子协程退出前将 innerWg 的计数器减一
        fmt.Printf("子协程一正在执行")
      }
      innerWg.Add(1)
      go func(){
        defer innerWg.Done() // 子协程退出前将 innerWg 的计数器减一
        fmt.Printf("子协程二正在执行")
      }
      innerWg.Wait() // 等所有所有子协程执行完才继续往下执行
      fmt.Printf("外层协程%d即将执行完毕", idx)
    }(idx)
  }
  wg.Wait() // 等待 wg 的计数器减为0后才继续往下执行,等待所有的协程处理完毕
  fmt.Println("Execution completed. will exit")
}
func main() {
  handleTask()
}
  • sync.WaitGroup{}:一个内部加锁的计数器,Add(num) 函数会使计数器加上对应的 num 值;Done() 函数会使计数器减一;Wait() 函数会一直阻塞程序的继续向下运行,直到计数器减为0。
  • Add() 函数需要在子协程开辟前执行;Done() 函数最好在子协程最开始的 defer 中执行,保证子协程退出后一定会将计数器减一,否则主协程可能因为计数器不为 0 一直卡主;Wait() 函数一般放在主协程里,且是子协程执行完毕后。
  • 如果需要控制协程的数量,还得引入 channel ,参考:5、Go是否可以无限go? 如何限定数量?,文末是从此文拷贝过来的一段代码

下面是内层子协程并发的另一种写法

博客平台纯手敲,可能存在字符拼写错误

import (
  "fmt"
  "sync"  
)
func handleTask() {
  demoList := []string{"123", "456", "abc", "ddd"}
  var wg = sync.WaitGroup{}
  for idx, item := range demoList {
    // 每个元素创建一个新协程去处理
    wg.Add(1) // 
    go func(idx int){
      defer wg.Done() // 协程退出前将 wg 计数器减一,否则最后计数器无法减为0,会一直卡在 wg.wait() 那一行
      // 内部还想新建子协程去做不同的事,减少执行时间
      var innerWg = sync.WaitGroup{} // 
      for i := 1; i < 3; i++ {
        innerWg.Add(1)
        go func(){
          defer innerWg.Done() // 子协程退出前将 innerWg 的计数器减一
          fmt.Printf("子协程 %d 正在执行\n", i)
        }
      }
      fmt.Printf("外层协程%d即将执行完毕", idx)
    }(idx)
  }
  wg.Wait() // 等待 wg 的计数器减为0后才继续往下执行,等待所有的协程处理完毕
  fmt.Println("Execution completed. will exit")
}
func main() {
  handleTask()
}

channel 与 sync 同步组合方式控制协程数量

代码来自:5、Go是否可以无限go? 如何限定数量?

package main
import (
    "fmt"
    "math"
    "sync"
    "runtime"
)
var wg = sync.WaitGroup{}
func busi(ch chan bool, i int) {
    fmt.Println("go func ", i, " goroutine count = ", runtime.NumGoroutine())
    <-ch
    wg.Done()
}
func main() {
    //模拟用户需求go业务的数量
    task_cnt := math.MaxInt64
    ch := make(chan bool, 3)
    for i := 0; i < task_cnt; i++ {
    wg.Add(1)
        ch <- true
        go busi(ch, i)
    }
    wg.Wait()
}

参考5、Go是否可以无限go? 如何限定数量?

相关文章
|
3月前
|
安全 Go
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
100 4
|
18天前
|
JavaScript 前端开发 测试技术
在 golang 中执行 javascript 代码的方案详解
本文介绍了在 Golang 中执行 JavaScript 代码的四种方法:使用 `otto` 和 `goja` 嵌入式 JavaScript 引擎、通过 `os/exec` 调用 Node.js 外部进程以及使用 WebView 嵌入浏览器。每种方法都有其适用场景,如嵌入简单脚本、运行复杂 Node.js 脚本或在桌面应用中显示 Web 内容。
51 15
在 golang 中执行 javascript 代码的方案详解
|
20天前
|
运维 监控 Cloud Native
一行代码都不改,Golang 应用链路指标日志全知道
本文将通过阿里云开源的 Golang Agent,帮助用户实现“一行代码都不改”就能获取到应用产生的各种观测数据,同时提升运维团队和研发团队的幸福感。
|
1月前
|
存储 安全 测试技术
GoLang协程Goroutiney原理与GMP模型详解
本文详细介绍了Go语言中的Goroutine及其背后的GMP模型。Goroutine是Go语言中的一种轻量级线程,由Go运行时管理,支持高效的并发编程。文章讲解了Goroutine的创建、调度、上下文切换和栈管理等核心机制,并通过示例代码展示了如何使用Goroutine。GMP模型(Goroutine、Processor、Machine)是Go运行时调度Goroutine的基础,通过合理的调度策略,实现了高并发和高性能的程序执行。
106 29
|
1月前
|
Go 计算机视觉
在Golang高并发环境中如何进行协程同步?
在此示例中,使用互斥锁来保护对共享计数器变量 c 的访问,确保并发的 HTTP 请求不会产生数据竞争。
45 3
|
1月前
|
负载均衡 算法 Go
GoLang协程Goroutiney原理与GMP模型详解
【11月更文挑战第4天】Goroutine 是 Go 语言中的轻量级线程,由 Go 运行时管理,创建和销毁开销小,适合高并发场景。其调度采用非抢占式和协作式多任务处理结合的方式。GMP 模型包括 G(Goroutine)、M(系统线程)和 P(逻辑处理器),通过工作窃取算法实现负载均衡,确保高效利用系统资源。
|
2月前
|
安全 Go 调度
探索Go语言的并发模式:协程与通道的协同作用
Go语言以其并发能力闻名于世,而协程(goroutine)和通道(channel)是实现并发的两大利器。本文将深入了解Go语言中协程的轻量级特性,探讨如何利用通道进行协程间的安全通信,并通过实际案例演示如何将这两者结合起来,构建高效且可靠的并发系统。
|
3月前
|
Go 调度
Golang语言goroutine协程篇
这篇文章是关于Go语言goroutine协程的详细教程,涵盖了并发编程的常见术语、goroutine的创建和调度、使用sync.WaitGroup控制协程退出以及如何通过GOMAXPROCS设置程序并发时占用的CPU逻辑核心数。
72 4
Golang语言goroutine协程篇
|
3月前
|
数据采集 消息中间件 并行计算
进程、线程与协程:并发执行的三种重要概念与应用
进程、线程与协程:并发执行的三种重要概念与应用
74 0
|
4月前
|
人工智能 Go
Golang 搭建 WebSocket 应用(二) - 基本群聊 demo
Golang 搭建 WebSocket 应用(二) - 基本群聊 demo
45 1