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

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

所有 goroutine 都睡著了,陷入僵局

所有 goroutine 都睡著了,陷入僵局

Go
智慧大石 2023-07-10 16:30:57
似乎無法弄清楚為什么我收到錯誤消息:致命錯誤:所有 goroutine 都在睡覺 - 死鎖!。我懷疑下面的塊中發生了競爭條件,該條件只能在通道關閉后執行。我認為添加同步 WaitGroup 會有所幫助,但這只會給我帶來這種僵局。我所看到的與我在網上看到的示例很接近,所以我不確定這里出了什么問題。func S3UploadFolder(instance *confighelper.Instance, sess *session.Session,     srcFolder string, bucketName string) (err error) {    log.Println("S3UploadFolder", srcFolder, bucketName)    wg := &sync.WaitGroup{}    // find files recursively    walker := make(fileWalk)    wg.Add(1)    go func() {        // Gather the files to upload by walking the path recursively        if err := filepath.Walk(srcFolder, walker.Walk); err != nil {            log.Fatalln("Walk failed:", err)        }        wg.Done()        close(walker)    }()    wg.Wait()    for path := range walker {    // THE GO routine above needs to have finished by the time this for loop        // ranges over the channel         fmt.Println(path) }return}type fileWalk chan stringfunc (f fileWalk) Walk(path string, info os.FileInfo, err error) error {    if err != nil {        return err    }    if !info.IsDir() {        f <- path    }    return nil}
查看完整描述

2 回答

?
牛魔王的故事

TA貢獻1830條經驗 獲得超3個贊

該walker通道是無緩沖的。在發送方和接收方準備就緒之前,無緩沖通道上的通信不會繼續進行。


死鎖是這樣的:主 goroutine 通過調用 wg.Done() 等待 walker goroutine 完成。walker goroutine 等待主 goroutine 在通道上接收。


通過刪除與等待組相關的所有代碼來修復程序。不需要等待組。在主 goroutine 中的通道范圍不會完成,直到通道被 walker goroutine 關閉。在步行完成之前,walker goroutine 不會關閉通道。不需要其他協調。


您還可以通過刪除 goroutine 和通道來修復代碼:


err := filepath.Walk(srcFolder, func(path string, info os.FileInfo, err error) error {

    if err != nil {

        return err

    }

    if info.IsDir() {

        return nil

    }


    // Insert body of for path := range walker here ... 

    fmt.Println(path)


    return nil

})

if err != nil {

    log.Fatal(err)

}

另一種選擇是創建一個容量大于將要遍歷的文件數量的緩沖通道,但這需要提前知道文件數量,并且與在切片中收集文件名相比沒有任何好處。


查看完整回答
反對 回復 2023-07-10
?
瀟瀟雨雨

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

如所寫(和所示),在運行循環之前絕對不能調用。您可以(但不需要)在循環終止時調用。您根本不需要該變量。wg.Wait()for path := range walkerwg.Wait()wg

你的評論說:

//?THE?GO?routine?above?needs?to?have?finished?by?the?time?this?for?loop?
//?ranges?over?the?channel

但是循環中沒有任何東西for要求函數完成,并且有一些東西(這里的總體策略)要求 goroutine不能在 send 中被阻塞,因為for只有當發送者(goroutine)時循環才會完成。關閉通道。

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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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