sync.WaitGroup – why one go routine comes after .wait()

huangapple go评论83阅读模式
英文:

sync.WaitGroup - why one go routine comes after .wait()

问题

我得到的翻译结果如下:

从以下内容中我得到了:
收到的蛋糕包装:草莓蛋糕
收到的蛋糕包装:草莓蛋糕
收到的蛋糕包装:草莓蛋糕
收到的蛋糕包装:草莓蛋糕
我们完成了!
收到的蛋糕包装:草莓蛋糕

我没想到"我们完成了!"会是倒数第二个?

package main

import (
	"fmt"
	// "strconv"
	// "time"
	"sync"
)

func makeCakeAndSend(cs chan string, wg *sync.WaitGroup) {
	cakeName := "草莓蛋糕"
	cs <- cakeName
	wg.Done()
}

func receiveCakeAndPack(cs chan string) {
	for s := range cs {
		fmt.Println("收到的蛋糕包装:", s)
	}
}

func main() {
	var wg sync.WaitGroup
	cs := make(chan string)

	wg.Add(5)

	for i := 1; i <= 5; i++ {
		go makeCakeAndSend(cs, &wg)
	}

	// go receiveCakeAndPack(cs)

	go func() {
		for s := range cs {
			fmt.Println("收到的蛋糕包装:", s)
		}
		close(cs)
	}()

	wg.Wait()

	fmt.Println("我们完成了!")

	var input string
	fmt.Scanln(&input)
}
英文:

From the following I get:<br>
Packing received cake: Strawberry Cake <br>
Packing received cake: Strawberry Cake <br>
Packing received cake: Strawberry Cake <br>
Packing received cake: Strawberry Cake <br>
We are done!<br>
Packing received cake: Strawberry Cake <br>

I did not expect "We are done!" to be second last?

package main

import (
	&quot;fmt&quot;
	// &quot;strconv&quot;
	// &quot;time&quot;
	&quot;sync&quot;
)

func makeCakeAndSend(cs chan string, wg *sync.WaitGroup) {
	cakeName := &quot;Strawberry Cake &quot;
	cs &lt;- cakeName
	wg.Done()
}

func receiveCakeAndPack(cs chan string) {
	for s := range cs {
		fmt.Println(&quot;Packing received cake: &quot;, s)
	}
}

func main() {
	var wg sync.WaitGroup
	cs := make(chan string)

	wg.Add(5)

	for i := 1; i &lt;= 5; i++ {
		go makeCakeAndSend(cs, &amp;wg)
	}

	// go receiveCakeAndPack(cs)

	go func() {
		for s := range cs {
			fmt.Println(&quot;Packing received cake: &quot;, s)
		}
		close(cs)
	}()

	wg.Wait()

	fmt.Println(&quot;We are done!&quot;)

	var input string
	fmt.Scanln(&amp;input)
}

答案1

得分: 4

这是完全正常的。wg.Wait() 确保在继续之前,所有的 goroutine 都完成了向通道发送数据的操作,但它并不同步打印出 "Packing received cake"。

当每个人都完成向通道发送数据后,通道中会有一个项目,对吗?但是 Waitgroup 已经完成了。

因此,你会遇到一个竞争条件,主 goroutine 继续执行 "we are done",而接收 goroutine 接收并打印数据。这并不是同步的,你无法保证哪个会先发生。

英文:

It's perfectly normal. The wg.Wait() makes sure that all goroutines finished sending data to the channel before we continue, it doesn't synchronize the prints of "Packing received cake".

When everyone has finished sending the data down the channel, the channel has one item in it, right? but the Waitgroup is finished.

So you have a race condition where the main goroutine continues to "we are done" and the receiving goroutine receives and prints. This is not synchronized and you have no guarantee which will happen first.

huangapple
  • 本文由 发表于 2016年1月3日 19:02:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/34575778.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定