Golang中Waitgroup计数器的执行顺序问题

Golang中Waitgroup计数器的执行顺序问题 我第一次使用等待组。我运行了代码,但代码执行的顺序与我的预期相反。 预期结果: Hello, playground Counter: 0 Counter: 1

请帮助我。 https://play.golang.org/p/U4TDVTbDzN4

3 回复

感谢您的帮助。 真的非常感谢。

更多关于Golang中Waitgroup计数器的执行顺序问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你的预期是错误的。goroutine 调度器并非确定性的。

package main

import (
	"fmt"
	"sync"
)

var wg sync.WaitGroup

func printer(counter int) {
	fmt.Println("Counter:\t", counter)
	wg.Done()
}

func main() {
	counter := 0
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go printer(counter)
		counter++
	}
	wg.Wait()
}

https://play.golang.org/p/wMs_I-7MRxN

. 运行 1: Counter: 9 Counter: 0 Counter: 1 Counter: 2 Counter: 3 Counter: 4 Counter: 5 Counter: 7 Counter: 6 Counter: 8 . 运行 2: Counter: 9 Counter: 0 Counter: 1 Counter: 5 Counter: 2 Counter: 3 Counter: 4 Counter: 7 Counter: 6 Counter: 8 . 运行 3: Counter: 9 Counter: 3 Counter: 0 Counter: 1 Counter: 2 Counter: 6 Counter: 4 Counter: 5 Counter: 7 Counter: 8 .

在Go语言中,sync.WaitGroup 的计数器操作顺序确实会影响并发执行的结果。根据你提供的代码链接,问题在于 wg.Add(1)wg.Done() 的调用时机。

以下是修正后的代码示例:

package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup
	
	for i := 0; i < 2; i++ {
		wg.Add(1) // 在启动goroutine前增加计数器
		go func(x int) {
			defer wg.Done() // 使用defer确保计数器减少
			fmt.Printf("Counter:\t %d\n", x)
		}(i)
	}
	
	fmt.Println("Hello, playground")
	wg.Wait() // 等待所有goroutine完成
}

关键点:

  1. wg.Add(1) 必须在每个goroutine启动前调用
  2. 使用 defer wg.Done() 确保goroutine结束时减少计数器
  3. wg.Wait() 会阻塞直到计数器归零

执行顺序:

  • 主goroutine先打印 “Hello, playground”
  • 两个goroutine并发执行,输出顺序可能为 0,1 或 1,0
  • wg.Wait() 确保所有goroutine完成后再退出程序

如果你需要严格的顺序输出,需要使用同步机制如通道或互斥锁,而不是WaitGroup。

回到顶部