gpt4 book ai didi

arrays - Golang 互斥范围遍及 goroutine 中的共享数组

转载 作者:IT王子 更新时间:2023-10-29 02:27:34 25 4
gpt4 key购买 nike

假设我有以下代码:

a := []int{1,2,3}
i := 0
var mu = &sync.Mutex{}
for i < 10 {
go func(a *[]int) {
for _, i := range a {
mu.Lock()
fmt.Println(a[0])
mu.Unlock()
}
}(&a)
i++
}

数组是共享资源,正在循环中读取。如何保护循环 header 中的数组,我是否需要这样做?还有必要将数组作为指针传递给goroutine吗?

最佳答案

首先,一些 Go 术语:

[]int{1, 2, 3} 是一个 slice ,而不是一个数组。数组将写为 [...]int{1, 2, 3}

slice 是 (start, length, capacity) 的三元组并指向底层数组(通常是堆分配的,但这是语言完全向您隐藏的实现细节!)

Go 的内存模型允许任意数量的读取器或(但不是和)至多一个写入器到内存中的任何给定区域。 Go memory model (不幸的是)没有特别指出同时访问同一个 slice 中的多个索引的情况,但这样做似乎很好(即它们被视为内存中的不同位置,正如预期的那样)。

因此,如果您只是从中读取,则根本没有必要保护它。

如果您正在读取写入它,但是 goroutines 不会在彼此相同的地方读取和写入(例如,如果 goroutine i只读取和写入位置 i) 那么你也不需要同步。此外,您可以同步整个 slice (这意味着更少的互斥锁,但争用)或者您可以同步 slice 中的各个位置(这意味着更少的争用但获得更多的互斥锁和锁并发布)。

但是因为 Go 允许函数在范围内捕获变量(也就是说,它们是闭包)所以根本没有理由将数组作为指针传递:

因此,您的代码最惯用的写法是:

a := []int{1,2,3}
for i := 0; i < 10; i++
for i < 10 {
go func() {
for _, i := range a {
fmt.Println(a[0])
}
}()
}

我不太确定上面的代码应该用来做什么——因为它会在各种 goroutine 中打印出 a[0] 10 次,这让它看起来好像不是以有意义的方式使用 slice 。

关于arrays - Golang 互斥范围遍及 goroutine 中的共享数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42238425/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com