【问题标题】:goroutine race condition solutiongoroutine 竞争条件解决方案
【发布时间】: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 开始之前完成执行。因此,如果我尝试设置时间,它会创建一个竞争条件。睡眠

标签: go concurrency 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 stackoverflow.com/q/36056615/9811969
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-11
  • 2012-02-22
相关资源
最近更新 更多