首页 >后端开发 >Golang >为什么 `wg.Add()` 的放置对于 Go 的 `sync.WaitGroup` 中的正确同步至关重要?

为什么 `wg.Add()` 的放置对于 Go 的 `sync.WaitGroup` 中的正确同步至关重要?

Linda Hamilton
Linda Hamilton原创
2024-10-30 01:49:02237浏览

  Why is the Placement of `wg.Add()` Crucial for Proper Synchronization in Go's `sync.WaitGroup`?

更正 wg.Add() 的 WaitGroup 同步位置

在 Go 中,sync.WaitGroup 类型提供 goroutine 之间的同步。它的主要目的是让主 goroutine 等待一组 goroutine 完成任务。然而,wg.Add() 调用的放置对于确保正确同步至关重要。

在错误的示例中:

<code class="go">var wg sync.WaitGroup
var v int32 = 0
for i := 0; i < 100; i++ {
    go func() {
        wg.Add(1) // Wrong place
        atomic.AddInt32(&v, 1)
        wg.Done()
    }()
}
wg.Wait()
fmt.Println(v)</code>

wg.Add(1) 调用放置在匿名函数,这是一个错误。这种错误的放置可能会导致 wg.Wait() 过早返回的情况,因为 wg.Add(1) 在同一 goroutine 中的 wg.Done() 之后执行。因此,v 将无法准确反映已完成任务的数量,其值可能会小于 100。

在更正的示例中:

<code class="go">var wg sync.WaitGroup
var v int32 = 0
for i := 0; i < 100; i++ {
    wg.Add(1)
    go func() {
        atomic.AddInt32(&v, 1)
        wg.Done()
    }()
}
wg.Wait()
fmt.Println(v)</code>

wg.Add( 1) call 现在被放置在匿名函数之外,确保主 goroutine 在调用 wg.Wait() 之前已经调用了所有 100 个 goroutine 并向 wg 注册了它们的完成任务。这个正确的放置保证了 wg.Wait() 将阻塞,直到所有 100 个 goroutine 完成其任务,从而获得准确的 v 值。

使用sync.WaitGroup 的一般规则:

为了确保使用sync.WaitGroup成功同步,请遵循以下准则:

  • 在启动新的goroutine之前,始终在主goroutine中调用wg.Add()。
  • 建议使用 defer 语句调用 wg.Done(),以确保即使在发生 Goroutine Panic 时也能执行。
  • 将sync.WaitGroup 传递给其他函数时(避免使用包级变量) ),向其传递一个指针以防止复制并确保所有更改均对原始的sync.WaitGroup进行。

以上是为什么 `wg.Add()` 的放置对于 Go 的 `sync.WaitGroup` 中的正确同步至关重要?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn