goroutine race condition 解决方案

goroutine race condition solution

我正在尝试了解如何为以下代码修复此竞争条件。

sayHello := func() {
    fmt.Println("Hello from goroutine")
}

go sayHello()
time.Sleep(1)

fmt.Println("Hello, playground")

期望:我只想知道最好的解决方案是什么,我应该使用 WaitGroup 还是有更好的解决方案?

所以我想出了以下解决方案:

var wg sync.WaitGroup
//defer wg.Wait()
sayHello := func() {
    defer wg.Done()
    fmt.Println("Hello from goroutine")
}
wg.Add(1)

go sayHello()
wg.Wait()

fmt.Println("Hello, playground")

但是它会阻塞主 goroutine 直到代码被执行!

同样,如果我使用 defer wg.Wait(),输出是不同的! https://play.golang.org/p/_xkLb7HvNF8

竞争条件我的意思是 go sayHello() 甚至从未执行过,因为 main func 将在 goroutine 启动之前完成执行。因此,如果我尝试将 time.Sleep

您的代码中没有 race condition

第一题

But its blocking the main goroutine until code is executed !

您在 sayHello 调用后立即使用:

wg.Wait()

这会阻塞您的代码并等待 goroutine 执行。因此,go sayHello() 将始终在 "Hello, playground".

之前打印 "Hello from goroutine"

查看文档 here:

Wait blocks until the WaitGroup counter is zero.

第二题

As well, if I use defer wg.Wait() the output is different !

是的,在这种情况下wg.Wait()将在退出主函数之前执行。这意味着 sayHello() 将在 之前打印 "Hello from goroutine" 或在 "Hello, playground" 之后打印 - 这取决于 Go scheduler

查看更多关于 defer here

A defer statement pushes a function call onto a list. The list of saved calls is executed after the surrounding function returns. Defer is commonly used to simplify functions that perform various clean-up actions.

更新:

与使用通道的其他解决方案相比,建议使用 WaitGroup。你应该在正确的地方使用 wg.Wait() 来达到预期的输出(仍然没有提供)。