亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

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

Go 中的通道阻塞是如何工作的?

Go 中的通道阻塞是如何工作的?

Go
江戶川亂折騰 2021-11-08 14:47:28
我正在學習 Go 語言。這是我遇到的一個例子。有人可以解釋一下這里發生了什么嗎?package mainimport "time"import "fmt"func main() {    c1 := make(chan string)    c2 := make(chan string)    go func() {        time.Sleep(time.Second * 1)        c1 <- "one"    }()    go func() {        time.Sleep(time.Second * 2)        c2 <- "two"    }()    for i := 0; i < 2; i++ {      select {        case msg1 := <-c1:          fmt.Println("received", msg1)        case msg2 := <-c2:          fmt.Println("received", msg2)        default:          fmt.Println("Default")      }    }}輸出:DefaultDefaultProgram Exited如果我注釋掉默認部分//default://    fmt.Println("Default")輸出變為:received onereceived twoProgram exited.default案例的存在如何改變通道阻塞的工作方式?
查看完整描述

2 回答

?
慕的地6264312

TA貢獻1817條經驗 獲得超6個贊

這與select語句在 Go 中的工作方式有關。

Go 文檔中select

如果可以進行一個或多個通信,則通過統一偽隨機選擇選擇可以進行的單個通信。否則,如果存在默認情況,則選擇該情況。如果沒有默認情況,“select”語句會阻塞,直到至少有一個通信可以繼續。

因此,如果沒有默認情況,代碼將一直阻塞,直到任一通道中的某些數據可用。它隱式地等待其他 goroutines 喚醒并寫入它們的通道。

當您添加 default case 時,很可能select在其他 goroutines 從睡眠中醒來之前到達該語句。

因此,由于(尚)沒有可用數據,并且存在默認情況,因此會執行默認情況。此操作進行兩次,耗時不到 1 秒。所以程序在任何 go 例程有機會喚醒并寫入通道之前終止。

請注意,這在技術上是一種競爭條件;絕對不能保證循環的 2 次迭代會在任何 go 例程喚醒之前運行,因此理論上即使在默認情況下也可能有不同的輸出,但實際上這是極不可能的。


查看完整回答
反對 回復 2021-11-08
?
拉莫斯之舞

TA貢獻1820條經驗 獲得超10個贊

select語句會阻塞,直到至少一個 case 準備就緒。Go 語言規范部分內容如下:

如果可以進行一個或多個通信,則通過統一偽隨機選擇選擇可以進行的單個通信。否則,如果存在默認情況,則選擇該情況。如果沒有默認情況,“select”語句會阻塞,直到至少有一個通信可以繼續。

在原始代碼中,default案例在循環的兩次迭代中都已準備就緒,因為在c1或上發送任何內容之前存在延遲c2。

刪除default案例后,select語句必須等待數據在c1或 中可用c2。


查看完整回答
反對 回復 2021-11-08
  • 2 回答
  • 0 關注
  • 321 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號