第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

嘗試兩次接收值時出現(xiàn)死鎖

嘗試兩次接收值時出現(xiàn)死鎖

Go
慕哥9229398 2021-08-16 19:47:27
我觀看了關(guān)于高級 Go 并發(fā)模式的精彩視頻。一開始,Sameer Ajmani 展示了一個乒乓應(yīng)用程序。package mainimport (    "fmt"    "time")type Ball struct{ hits int }func main() {    table := make(chan *Ball)    go player("ping", table)    go player("pong", table)    table <- new(Ball) // game on; toss the ball    time.Sleep(1 * time.Second)    fmt.Println(<-table) // game over; grab the ball}func player(name string, table chan *Ball) {    for {        ball := <-table        ball.hits++        fmt.Println(name, ball.hits)        time.Sleep(100 * time.Millisecond)        table <- ball    }}代碼是如何工作的,我理解到 90%。它們是兩個 goroutine,它們在主線程休眠期間相互發(fā)送消息,ping 和 pong。然后我嘗試跟隨package mainimport (    "fmt"    "time")type Ball struct{ hits int }func main() {    table := make(chan *Ball)    go player("ping", table)    go player("pong", table)    table <- new(Ball) // game on; toss the ball    time.Sleep(1 * time.Second)    fmt.Println(<-table) // game over; grab the ball    fmt.Println(<-table) // game over; grab the ball}func player(name string, table chan *Ball) {    for {        ball := <-table        ball.hits++        fmt.Println(name, ball.hits)        time.Sleep(100 * time.Millisecond)        table <- ball    }}我在這里陷入僵局,真的不明白為什么。查看 go 例程中的最后一行,我嘗試像倒數(shù)第二行一樣從通道接收值。在后臺,兩個 goroutine 仍然繼續(xù)循環(huán)并相互發(fā)送值。對我來說,它似乎是表變量通道的多個接收器。我的主要問題是,我在第二個樣本中遇到了什么僵局?
查看完整描述

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被寫入

  • Maintable使用以下行將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)閉頻道。但是,我希望這次討論能消除您的困惑。


查看完整回答
反對 回復 2021-08-16
  • 1 回答
  • 0 關(guān)注
  • 190 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號