1. 程式人生 > 其它 >golang中channel的happened-before講解

golang中channel的happened-before講解

關於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 之前