goroutine 竞争条件解决方案

Posted

技术标签:

【中文标题】goroutine 竞争条件解决方案【英文标题】:goroutine race condition solution 【发布时间】:2019-08-20 06:36:08 【问题描述】:

我正在尝试了解如何解决以下代码的这种竞争条件。

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() 甚至永远不会被执行,因为主函数将在 goroutine 开始之前完成执行。因此,如果我尝试设置 time.Sleep,它会产生竞争条件

【问题讨论】:

竞态条件是什么?你希望 goroutine 的打印在 main 的打印之前显示? 我没有看到竞争条件。 竞争条件 我的意思是go sayHellow() 甚至永远不会被执行,因为主函数会在 goroutine 开始之前完成执行。因此,如果我尝试设置时间,它会创建一个竞争条件。睡眠 【参考方案1】:

您的代码中没有race condition。

第一个问题

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

您在sayHello 调用后立即使用:

wg.Wait()

这会阻塞你的代码并等待 goroutine 被执行。因此,go sayHello() 将始终在 "Hello, playground" 之前打印 "Hello from goroutine"

参见文档here:

等待块直到 WaitGroup 计数器为零。

第二个问题

同样,如果我使用 defer wg.Wait() 输出是不同的!

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

查看更多关于deferhere

defer 语句将函数调用推送到列表中。保存的调用列表在周围函数返回后执行。 Defer 通常用于简化执行各种清理操作的函数。

更新:

与使用渠道的其他解决方案相比,建议使用WaitGroup。您应该在正确的位置使用wg.Wait() 以实现预期的输出(仍未提供)。

【讨论】:

谢谢。你也能建议什么是最好的代码吗?我的意思是我该如何解决它 你能用预期的输出扩展你的问题吗? 使用 WaitGroup 是最好的。在这里查看两种解决方案的比较:WaitGroup vs channels ***.com/q/36056615/9811969

以上是关于goroutine 竞争条件解决方案的主要内容,如果未能解决你的问题,请参考以下文章

基于共享变量的并发

sync:与golang的并发息息相关的包

如何修复条件变量等待/通知的竞争条件

多线程系列Race Condition的产生和解决

如何在库存分配方案中阻止这种竞争条件? [关闭]

Java MySQL 防止竞争条件