首页 > 其他分享 >golang 协程并发代码 demo

golang 协程并发代码 demo

时间:2022-12-16 11:38:59浏览次数:56  
标签:wg 协程 demo golang 计数器 innerWg func go

有时我们可能想既在外层循环中实现多协程并发,还想在内层循环中实现多协程并发,那么我们需要同时在内层和外层使用 ​​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? 如何限定数量?​



标签:wg,协程,demo,golang,计数器,innerWg,func,go
From: https://blog.51cto.com/u_14201949/5946998

相关文章

  • Demo of canvas, canvas optimization and svg
    Itusedthecanvastodrawthecurvesintheoldproject,andtheclientfeltthatitwasvague,soItriedtomakeademoaboutcanvas,canvasoptimizationan......
  • Kotlin 并发编程之"协程"
    Kotlin协程简介 Kotlin,asalanguage,providesonlyminimallow-levelAPIsinitsstandardlibrarytoenablevariousotherlibrariestoutilizecoroutines.Unl......
  • Demo
    优势1、链接笔记2、开源插件和CSS3、Markdown4、自由度1)文件库自由定-提桶跑路2)样式教程具体:1、笔记范例(https://cdn.sspai.com/2021/06/24/ec388ab232abcd5fd9......
  • 关于C++20协程的系列文章
    https://www.cnblogs.com/ishen/p/14617708.html https://www.bennyhuo.com/2022/03/20/cpp-coroutines-05-dispatcher/ https://matpool.com/blog/6048282f505b8f00......
  • golang操作数据库-mysql&mongodb
    安装驱动goget-ugithub.com/go-sql-driver/mysql初始化模块gomodinitm执行gomodtidygomodtidy导入驱动packagemainimport"fmt"database/sq1'"github.com/go-sql-......
  • goLang包以及并发编程
    1包包可以区分命名空间,一个文件夹中不能有两个同名文件,go中创建一个包一般是创建一个文件夹,在该文件夹里面的go文件中使用关键字package声明包名称,通常文件夹名称和包名称......
  • 【Python多任务--进程,协程】
    一、进程进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。进程是线程的容器,一个进程可以有多个线程进程特......
  • CAD二开-反应器Demo
    CAD反应器定义AppRLReactor类,继承AppBaseReactor类以下是测试代码#pragmaonce#include"AppBaseReactor.h"classAppRLReactor:publicAppBaseReactor{public......
  • python并发编程之asyncio协程(三)
    协程实现了在单线程下的并发,每一个协程共享线程的几乎全部的资源,除了协程本身私有的上下文栈;协程的切换属于程序级别的切换,对于操做系统来讲是无感知的,所以切换速度更快、......
  • golang的module管理与使用go mod
    #############################  更换或升级了golang后,需要删除go.mod、go.sum、vendor文件,然后重建,不然一直卡在那里      使用: Gomodules操作命令及相关文件解......