我试图理解为什么两段相似的代码表现不同。这两个片段都创建了大量的 goroutine,它们尝试同时附加到同一个切片,我认为这是一种竞争条件。然而,第一个片段会出现恐慌,而第二个片段则不会。
以下是片段:
片段1:
package main
func main() {
for i := 0; i < 100000; i++ {
var arr []int
go func() {
arr = append(arr, 1)
}()
go func() {
arr = append(arr, 1)
}()
}
}
片段2:
package main
func main() {
var arr []int
for i := 0; i < 100000; i++ {
go func() {
arr = append(arr, 1)
}()
go func() {
arr = append(arr, 1)
}()
}
}
任何人都可以帮助我理解为什么第一个片段会出现恐慌,而第二个片段却不会?预先感谢您的帮助!
大家都能猜到。
在第一个示例中,您生成了许多生长相同(零)切片的 goroutine 对,因此一个例程看到另一个例程未完成的结果的变化很大,这意味着部分初始化的
arr
切片。
在第二个示例中,您主要写入同一个切片,因此并发 goroutine 会覆盖另一个 goroutine 的数据,但是当一个例程追加一个元素并将新长度设置为 5 时,另一个例程会覆盖一个元素并将长度设置为 4只是有无效数据,但没有崩溃。
在这两种情况下,您都有无效数据,但由于崩溃,在第一种情况下更容易检测到,而通过
-race
标志会检测第二种情况。
请注意,竞争检测器不会检测所有数据竞争,并且不同 CPU 架构上的竞争结果有所不同,因此请注意文档中指定的假定行为。