我很难理解并发/并行。在我的代码中,我做了一个5个循环的循环。在循环内部,我添加了wg.Add(1)
,总共有5个Add
。这是代码:
package main
import (
"fmt"
"sync"
)
func main() {
var list []int
wg := sync.WaitGroup{}
for i := 0; i < 5; i++ {
wg.Add(1)
go func(c *[]int, i int) {
*c = append(*c, i)
wg.Done()
}(&list, i)
}
wg.Wait()
fmt.Println(len(list))
}
主函数等待所有goroutine完成,但是当我尝试打印slice的长度时,会得到随机结果。 ex(1,3,etc)是否缺少某些东西才能获得预期的结果,即5?
最佳答案
获得预期结果(例如5)是否缺少某些东西?
是的,正确的同步。如果多个goroutine在其中至少一个为写操作的情况下访问同一个变量,则需要显式同步。
您的示例可以使用单个互斥锁“保护”:
var list []int
wg := sync.WaitGroup{}
mu := &sync.Mutex{} // A mutex
for i := 0; i < 5; i++ {
wg.Add(1)
go func(c *[]int, i int) {
mu.Lock() // Must lock before accessing shared resource
*c = append(*c, i)
mu.Unlock() // Unlock when we're done with it
wg.Done()
}(&list, i)
}
wg.Wait()
fmt.Println(len(list))
这将始终打印5。
注意:最后读取同一片以打印其长度,但此处未使用互斥锁。这是因为使用waitgroup可以确保我们只能在所有修改它的goroutine完成其工作之后才能到达该点,因此数据争用不会在那里发生。但通常来说,读取和写入都必须同步。
查看可能的重复项:
go routine not collecting all objects from channel
Server instances with multiple users
Why does this code cause data race?
How safe are Golang maps for concurrent Read/Write operations?
golang struct concurrent read and write without Lock is also running ok?
查看相关问题:
Can I concurrently write different slice elements
If I am using channels properly should I need to use mutexes?
Is it safe to read a function pointer concurrently without a lock?
Concurrent access to maps with 'range' in Go