这段代码会不会在 Go1.5 的 GC 之后引起 panic?
Would this code cause a panic after GC in Go1.5?
package main
import "time"
var x = []string{}
func main() {
go func() {
for {
y := x
y = append(y, "aa")
}
}()
go func() {
for {
x = []string{"123"}
}
}()
for {
time.Sleep(1)
}
}
猜猜x(比如123的地址)并没有真正分配给y,而x被分配给了一个新的地址,比如124。
而恰好这次gc了,123的地址会不会被回收造成panic?
没有。首先,x 具有全局范围。因此,在为其分配具有新地址的新值之前,GC 不会发生。
现在,当分配一个新值时,可能会发生两件事:
- Goroutine 将 y 分配给 x。它被分配给 y。那么GC就不会发生了。
- 在第一步发生之前,它将使用新地址获取新值。
我不知道你想做什么。但是即使 goroutine 同时运行也不会出现 panic。 X 总是有一个值。
既然你问过赋值是否是原子的:没有正常的赋值是原子的。
"is not really assigned" - 什么,go里面没有这个东西
您的代码存在竞争条件 go run -race
,它写入 "x",从 "x" 读取并同时增长 "x" 的切片。
"y := x" 通常不是原子的,它取决于值,但对于 slice/interface{}/map/struct 肯定不是原子的。有 sync.atomic 个原子基元包。
package main
import "time"
var x = []string{}
func main() {
go func() {
for {
y := x
y = append(y, "aa")
}
}()
go func() {
for {
x = []string{"123"}
}
}()
for {
time.Sleep(1)
}
}
猜猜x(比如123的地址)并没有真正分配给y,而x被分配给了一个新的地址,比如124。 而恰好这次gc了,123的地址会不会被回收造成panic?
没有。首先,x 具有全局范围。因此,在为其分配具有新地址的新值之前,GC 不会发生。
现在,当分配一个新值时,可能会发生两件事:
- Goroutine 将 y 分配给 x。它被分配给 y。那么GC就不会发生了。
- 在第一步发生之前,它将使用新地址获取新值。
我不知道你想做什么。但是即使 goroutine 同时运行也不会出现 panic。 X 总是有一个值。
既然你问过赋值是否是原子的:没有正常的赋值是原子的。
"is not really assigned" - 什么,go里面没有这个东西
您的代码存在竞争条件 go run -race
,它写入 "x",从 "x" 读取并同时增长 "x" 的切片。
"y := x" 通常不是原子的,它取决于值,但对于 slice/interface{}/map/struct 肯定不是原子的。有 sync.atomic 个原子基元包。