package mainimport ( "fmt")func write(ch chan int) { for i := 0; i < 5; i++ { fmt.Println("avaliable", i) ch <- i fmt.Println("successfully wrote", i, "to ch") } close(ch)}func main() { ch := make(chan int) go write(ch) for v := range ch { fmt.Println("read value", v, "from ch") }}輸出avaliable 0successfully wrote 0 to chavaliable 1read value 0 from chread value 1 from chsuccessfully wrote 1 to chavaliable 2successfully wrote 2 to chavaliable 3read value 2 from chread value 3 from chsuccessfully wrote 3 to chavaliable 4successfully wrote 4 to chread value 4 from ch由于這是一個無緩沖的通道,它應該在數(shù)據(jù)寫入它時立即阻塞,直到另一個 goroutine 從同一通道讀取。但它接受的數(shù)據(jù)超出了它的能力。預期行為package mainimport ( "fmt" "time")func write(ch chan int) { for i := 0; i < 5; i++ { fmt.Println("avaliable", i) ch <- i fmt.Println("successfully wrote", i, "to ch") } close(ch)}func main() { ch := make(chan int) go write(ch) time.Sleep(time.Second) for v := range ch { fmt.Println("read value", v, "from ch") time.Sleep(time.Second) }}輸出avaliable 0read value 0 from chsuccessfully wrote 0 to chavaliable 1read value 1 from chsuccessfully wrote 1 to chavaliable 2read value 2 from chsuccessfully wrote 2 to chavaliable 3read value 3 from chsuccessfully wrote 3 to chavaliable 4read value 4 from chsuccessfully wrote 4 to ch如果在整個代碼中放置了一些計時器,以便主 goroutine 在每次迭代之前被阻塞,它就會按預期工作。
2 回答

HUX布斯
TA貢獻1876條經(jīng)驗 獲得超6個贊
您無法從輸出中推斷出任何內容,因為“讀取值”和“成功寫入”Printfs 執(zhí)行之間沒有順序保證。(在通道發(fā)送之前發(fā)生的“可用”Printf 和在相應通道接收之后發(fā)生的“讀取值”Printf 之間存在一個,您可以看到輸出中永遠不會違反該順序)。
通道沒有緩沖任何東西,因為它沒有緩沖;只是通道發(fā)送完成后,兩個不同的 goroutine 以不確定的順序運行。有時發(fā)送方先走并打印“成功寫入”消息,有時接收方先走并打印“讀取值”消息。沒有一個“領先”超過一個值,因為它們仍然在通道發(fā)送上完全同步;他們只是在比賽之后立即打印他們的狀態(tài)消息。
當您將 Sleep 調用添加到 main 時,它恰好使運行的 goroutinewrite
在等待發(fā)送下一個值時總是被阻塞,而正在運行的 goroutinemain
在調用時阻塞Sleep
。當定時器超時時,主協(xié)程被喚醒,并立即發(fā)現(xiàn)它在通道上等待它的東西,抓住它,然后重新進入睡眠狀態(tài),然后write
協(xié)程被喚醒。通過放慢速度,您已經(jīng)讓調度程序以一致的順序運行事物(盡管這仍然部分是運氣問題);沒有睡眠,一切都盡可能快地運行,結果顯然是隨機的。
- 2 回答
- 0 關注
- 220 瀏覽
添加回答
舉報
0/150
提交
取消