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 调度程序
查看更多关于defer
here
defer 语句将函数调用推送到列表中。保存的调用列表在周围函数返回后执行。 Defer 通常用于简化执行各种清理操作的函数。
更新:
与使用渠道的其他解决方案相比,建议使用WaitGroup
。您应该在正确的位置使用wg.Wait()
以实现预期的输出(仍未提供)。
【讨论】:
谢谢。你也能建议什么是最好的代码吗?我的意思是我该如何解决它 你能用预期的输出扩展你的问题吗? 使用 WaitGroup 是最好的。在这里查看两种解决方案的比较:WaitGroup vs channels ***.com/q/36056615/9811969以上是关于goroutine 竞争条件解决方案的主要内容,如果未能解决你的问题,请参考以下文章