Go语言的坑: Happens Before 保证

[toc]

创建 goroutine 发生先于 goroutine 执行,所以下面这段代码先读一个变量,然后在 goroutine 中写变量不会发生 data race 问题:

1
2
3
4
i := 0
go func() {
i++
}()

goroutine 退出没有任何 happen before保证,例如下面代码会有 data race :

1
2
3
4
5
i := 0
go func() {
i++
}()
fmt.Println(i)

channel 操作中 send 操作是 happens before receive 操作 :

1
2
3
4
5
6
7
8
9
10
11
12
13
var c = make(chan int, 10)
var a string

func f() {
a = "hello, world"
c <- 0
}

func main() {
go f()
<-c
print(a)
}

上面执行顺序应该是:

1
variable change -> channel send -> channel receive -> variable read

上面能够保证一定输出 “hello, world”。

close channel 是 happens before receive 操作,所以下面这个例子中也不会有 data race 问题:

1
2
3
4
5
6
7
8
i := 0
ch := make(chan struct{})
go func() {
<-ch
fmt.Println(i)
}()
i++
close(ch)

在无缓冲的 channel 中 receive 操作是 happens before send 操作的,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
var c = make(chan int)
var a string

func f() {
a = "hello, world"
<-c
}

func main() {
go f()
c <- 0
print(a)
}

这里同样能保证输出 hello, world。