1 回答

TA貢獻1895條經(jīng)驗 獲得超3個贊
在后臺,兩個 goroutine 仍然繼續(xù)循環(huán)并相互發(fā)送值。
不,他們沒有。
當您使用 制作頻道時make(chan *Ball)
,您正在制作一個無緩沖的頻道。這相當于說make(chan *Ball,0)
,這意味著通道可以在其中容納 0 個東西 - 或者更明確地說,對通道的任何寫入都將阻塞,直到另一個例程從通道讀取,反之亦然。
無緩沖通道的執(zhí)行順序是這樣的:
玩家“ping”創(chuàng)建,嘗試從表中讀取
ball := <-table
,阻塞直到table
被寫入玩家“pong”創(chuàng)建,嘗試從表中讀取
ball := <-table
,阻塞直到table
被寫入Main
table
使用以下行將Ball 寫入:table <- new(Ball) // game on; toss the ball
這不會被阻止,因為有人正在等待在頻道上閱讀。
現(xiàn)在 ping 讀取球(在 ping 之后繼續(xù)執(zhí)行
ball := <-table
)Ping 把球放在桌子上
table <- ball
,沒有被擋住,因為 pong 正在等待Pong 讀球(在 pong 之后繼續(xù)執(zhí)行
ball := <-table
)Pong 把球放在桌子上
table <- ball
,沒有被擋住,因為 ping 正在等待ping 讀球(ping 后繼續(xù)執(zhí)行
ball := <-table
)....等等
直到主要通過閱讀球而不是其中一名球員來結(jié)束比賽
這是使用通道確保一次只運行一個例程的一個很好的示例。
為了結(jié)束游戲,主線程在一秒鐘后簡單地將球搶出通道:
time.Sleep(1 * time.Second) fmt.Println(<-table) // game over; grab the ball
在此之后,table
通道將是空的,任何進一步的讀取都會被阻塞。
此時,兩個
player
例程都被阻塞在ball := <- table
。
如果您<-table
在主線程中進一步讀取,該讀取也將阻塞,直到例程嘗試寫入表通道。但是,由于沒有其他例程在運行,因此會出現(xiàn)死鎖(所有 goroutine 都被阻塞)。
行。那么我可以在通道中放兩個球嗎?
不。
如果我們嘗試在通道中放入兩個球,我們可能會得到輸出:
Ping 1Pong 1
因為這兩個player
例程都會在試圖將球放回通道時被卡住 - 但沒有人會試圖閱讀它。訂單如下所示:
玩家“ping”創(chuàng)建,嘗試從表中讀取,被阻止
玩家“pong”創(chuàng)建,嘗試從表中讀取,被阻止
main 將第一個球放入
table
(未阻塞,因為有人在等待閱讀)main 將第二個球放入
table
(沒有被阻塞,因為有人在等待閱讀)平讀第一個球
龐讀第二個球
Ping 把第一個球放在桌子上,因為沒有人在等待閱讀而被阻止
Pong 把第二個球放在桌子上,因為沒人等著看,所以被擋住了
兩名球員都被封鎖
直到主要通過讀取兩個球來結(jié)束游戲。
正如評論者指出的那樣,結(jié)束游戲的更好做法是關(guān)閉頻道。但是,我希望這次討論能消除您的困惑。
- 1 回答
- 0 關(guān)注
- 190 瀏覽
添加回答
舉報