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

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

為什么這個 goroutine 不調用 wg.Done()?

為什么這個 goroutine 不調用 wg.Done()?

Go
揚帆大魚 2023-07-31 17:26:22
假設在任意時刻,registerChan 上最多有兩個元素(工作地址)。然后由于某種原因,下面的代碼沒有在最后兩個 goroutine 中調用 wg.Done() 。func schedule(jobName string, mapFiles []string, nReduce int, phase jobPhase, registerChan chan string) {    var ntasks int    var nOther int // number of inputs (for reduce) or outputs (for map)    switch phase {    case mapPhase:        ntasks = len(mapFiles)        nOther = nReduce    case reducePhase:        ntasks = nReduce        nOther = len(mapFiles)    }    fmt.Printf("Schedule: %v %v tasks (%d I/Os)\n", ntasks, phase, nOther)    const rpcname = "Worker.DoTask"    var wg sync.WaitGroup    for taskNumber := 0; taskNumber < ntasks; taskNumber++ {        file := mapFiles[taskNumber%len(mapFiles)]        taskArgs := DoTaskArgs{jobName, file, phase, taskNumber, nOther}        wg.Add(1)        go func(taskArgs DoTaskArgs) {            workerAddr := <-registerChan            print("hello\n")            // _ = call(workerAddr, rpcname, taskArgs, nil)            registerChan <- workerAddr            wg.Done()        }(taskArgs)    }    wg.Wait()    fmt.Printf("Schedule: %v done\n", phase)}如果我放在wg.Done()前面,registerChan <- workerAddr它就可以正常工作,但我不知道為什么。我也嘗試過推遲 wg.Done() 但這似乎不起作用,盡管我期望它能起作用。我認為我對 go 例程和通道的工作方式存在一些誤解,這導致了我的困惑。
查看完整描述

2 回答

?
慕無忌1623718

TA貢獻1744條經驗 獲得超4個贊

因為它在這里:

workerAddr?:=?<-registerChan

對于緩沖通道:
要使其workerAddr := <-registerChan正常工作:通道registerChan?必須有一個值;否則,代碼將在此停止等待通道


我設法以這種方式運行你的代碼(試試這個):

package main


import (

? ? "fmt"

? ? "sync"

)


func main() {

? ? registerChan := make(chan int, 1)

? ? for i := 1; i <= 10; i++ {

? ? ? ? wg.Add(1)

? ? ? ? go fn(i, registerChan)

? ? }

? ? registerChan <- 0 // seed

? ? wg.Wait()

? ? fmt.Println(<-registerChan)

}


func fn(taskArgs int, registerChan chan int) {

? ? workerAddr := <-registerChan

? ? workerAddr += taskArgs

? ? registerChan <- workerAddr

? ? wg.Done()

}


var wg sync.WaitGroup


輸出:


55

說明:

此代碼使用通道和 10 個 goroutine 加上一個主 goroutine 將 1 與 10 相加。


我希望這有幫助。


查看完整回答
反對 回復 2023-07-31
?
互換的青春

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

當您運行此語句時registerChan <- workerAddr,如果通道容量已滿,則無法添加它,并且它將阻塞。如果你有一個池,比如 10 個workerAddr,你可以在調用之前將它們全部添加到容量為 10 的緩沖通道中schedule。不要在調用后添加,以保證如果您從通道中獲取值,之后有空間再次添加它。defer在 goroutine 的開頭使用是很好的。



查看完整回答
反對 回復 2023-07-31
  • 2 回答
  • 0 關注
  • 178 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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