golang中channel的happened-before講解
阿新 • • 發佈:2022-02-18
關於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 之前