golang并发同步问题
golang concurrency sync issue
我在使用 goroutines 时遇到同步问题。我的程序输出不可预测的结果。我检查了文档,对于未缓冲的通道,无法检查是否所有消息都已处理。我将问题简化为仍然演示问题的这个小演示代码。显然,这不是 Golang 的问题,而是我的代码的问题。显然我没有使用正确的并发模式。
问题是如何解决这个问题。如果可能的话,我既不想关闭通道也不想停止 hive goroutine。如果我可以假设一旦所有蜜蜂 goroutine 都完成了,蜂巢现在也完成了,那会很棒(这就是我使用 wg.Wait() 尝试的方法)。
package main
import(
"fmt"
"sync"
"time"
)
func main() {
count := int64(0)
c := make(chan int64)
var wg sync.WaitGroup
// bees
for i:=0; i<5000;i++{
wg.Add(1)
go func(in chan int64) {
defer wg.Done()
time.Sleep(100)
in <- 2
}(c)
}
// hive
go func() {
for out := range c {
count += out
}
}()
wg.Wait()
// bang! but why?
fmt.Println(count)
}
// every now and again the program prints out before it is finished
// $ go run pattern1.go
// 10000
// $ go run pattern1.go
// 9998
// $ go run pattern1.go
// 9998
// $ go run pattern1.go
// 10000
// $ go run pattern1.go
// 10000
// $ go run pattern1.go
// 9998
您永远不会等待 "hive" 循环完成,因此有时您会在 count
循环完成之前打印它。
最简单的方法是使用 WaitGroup 发出信号何时关闭通道,并在 for range 循环上阻塞 main
:
go func() {
wg.Wait()
close(c)
}()
for out := range c {
count += out
}
我在使用 goroutines 时遇到同步问题。我的程序输出不可预测的结果。我检查了文档,对于未缓冲的通道,无法检查是否所有消息都已处理。我将问题简化为仍然演示问题的这个小演示代码。显然,这不是 Golang 的问题,而是我的代码的问题。显然我没有使用正确的并发模式。
问题是如何解决这个问题。如果可能的话,我既不想关闭通道也不想停止 hive goroutine。如果我可以假设一旦所有蜜蜂 goroutine 都完成了,蜂巢现在也完成了,那会很棒(这就是我使用 wg.Wait() 尝试的方法)。
package main
import(
"fmt"
"sync"
"time"
)
func main() {
count := int64(0)
c := make(chan int64)
var wg sync.WaitGroup
// bees
for i:=0; i<5000;i++{
wg.Add(1)
go func(in chan int64) {
defer wg.Done()
time.Sleep(100)
in <- 2
}(c)
}
// hive
go func() {
for out := range c {
count += out
}
}()
wg.Wait()
// bang! but why?
fmt.Println(count)
}
// every now and again the program prints out before it is finished
// $ go run pattern1.go
// 10000
// $ go run pattern1.go
// 9998
// $ go run pattern1.go
// 9998
// $ go run pattern1.go
// 10000
// $ go run pattern1.go
// 10000
// $ go run pattern1.go
// 9998
您永远不会等待 "hive" 循环完成,因此有时您会在 count
循环完成之前打印它。
最简单的方法是使用 WaitGroup 发出信号何时关闭通道,并在 for range 循环上阻塞 main
:
go func() {
wg.Wait()
close(c)
}()
for out := range c {
count += out
}