关于channel的happened-before有哪些
1. 第 n 个 send 一定 happened before 第 n 个 receive finished,无论是缓冲型还是非缓冲型的 channel。
2. 对于容量为 m 的缓冲型 channel,第 n 个 receive 一定 happened before 第 n+m 个 send finished。
3. 对于非缓冲型的 channel,第 n 个 receive 一定 happened before 第 n 个 send finished。
4. channel close 一定 happened before receiver 得到通知。
解释:
1. send不一定发生在recv之前,因为也可以先receive,然后goroutine被挂起,之后被sender唤醒,
无论如何,send一定发生在receive finished之前
2. 缓冲型channel,容量为m,第n+m个send发送之后的情形:
如果第n个receive还没发生,这时候channel填满了,send就会被阻塞,
当第n个receive接收完成后,sender goroutine会被唤醒,之后在继续发送过程
也就是说第n个receive happened-before 第n+m个send finished
3. 第n个send如果被阻塞了,sender goroutine被挂起,第n个receive到来时,先与第n个send finished
如果第n个send未被阻塞,说明第n个receive已经在那等着了,它不仅happened-before send finished
而且还happened-before send
4. 先设置closed = 1,在唤醒等待的receiver, 并将零值拷贝给receiver
案例:
// 顺序一致性的内存模型,这是并发编程的基础
var ch = make(chan bool)
var msg string
func AGoroutine() {
time.Sleep(time.Second)
msg = "哈哈"
<-ch
}
func main() {
go AGoroutine()
ch <- true
fmt.Println(msg) // 一定打印哈哈,为什么?
// 因为 对于无缓冲型通道,第n个receive一定发生在第n个send finished之前
}
// 这里依赖的就是前面讲的happened-before 第一条,send一定发生在receive finished之前,
// 即 ch <- true 在 <-ch 之前