sync.WaitGroup和sync.Once

sync.WaitGroup,顾名思义,等待一组goroutinue运行完毕。sync.WaitGroup声明后即可使用,它有如下方法:

  1. func (wg *WaitGroup) Add(delta int) #不能传入符数,否则引发panic
  2. func (wg *WaitGroup) Done()
  3. func (wg *WaitGroup) Wait()

一般套路是,"先统一Add, 在并发Done, 最后Wait"。中心思想是由一个goroutine或主程序来调用Add和Wait方法,其他goroutinue作为子任务调用done方法,否则会引发可能的panic异常。

sync.Once, 也是开箱即用的,声明后即可使用,只有一个方法:

  1. func (o *Once) Do(f func())

sync.Once需要注意以下两点,避免踩坑:

  1. 当多个goroutinue并发地调用同一个sync.Once实例时,如果传入的函数执行时间过长,由于sync.Once是使用锁机制,保证传入的函数只执行一次,因此会造成其他goroutinue函数的阻塞。
  2. sync.Once 有一个done的unint32的字段,取值只有0和1。只要Do方法执行完成,done就由0变为1。值得注意的是done由defer保证执行后一定会是1。
package main
import "sync"
import "fmt"
import "sync/atomic"
import "time"

const PI = 3.14
var w sync.WaitGroup
var once sync.Once
var doneTaskCount int32

func calCircleCircum(r float64, ret *float64) {
  defer w.Done()
  *ret = PI * r
  atomic.AddInt32(&doneTaskCount, 1)
  time.Sleep(time.Millisecond * 2000)
}

func calRectangleCircum(width float64, long float64, ret *float64) {
  defer w.Done()
  *ret = 2 * (long + width)
  atomic.AddInt32(&doneTaskCount, 1)
  time.Sleep(time.Millisecond * 1000)
}

func printResults(circleRet *float64, rectangleRet *float64) {
  
  once.Do(func(){
    for atomic.LoadInt32(&doneTaskCount) !=2 {
      fmt.Println("Wait sub task done.....")
      time.Sleep(time.Millisecond * 200)
    }
  })


  fmt.Printf("the cicle circumference is %1.2f\n", *circleRet)
  fmt.Printf("the rectangle circumference is %1.2f\n", *rectangleRet)
}

func main() {
  circleRet := 0.0
  rectangleRet := 0.0
  
  w.Add(2)
  go printResults(&circleRet, &rectangleRet)
  go calCircleCircum(2.0, &circleRet)
  go calRectangleCircum(2.0, 3.0, &rectangleRet)
  w.Wait()
}
posted @   yihailin  阅读(507)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
点击右上角即可分享
微信分享提示