简单程序死锁,无法识别原因

我在以下代码中遇到死锁错误,但我无法确定原因。代码的目标是以递归方式获取给定文件夹中所有文件的 sha256 哈希。(最终目标是根据哈希删除重复的文件,作为一个学习项目)


为此,它会发送一个 goroutine,为每个文件生成另一个 goroutine 以获取哈希值。哈希存储在通道中,并在简单循环中在代码末尾读取。


根据打印,检查所有文件,并检查wg。“添加”和“完成”似乎在正确的位置。


法典:


package main


import (

    "crypto/sha256"

    "fmt"

    "io"

    "io/fs"

    "log"

    "os"

    "path/filepath"

    "sync"

    "time"

)


func get_fsha256sum(filepath string) string {

    f, err := os.Open(filepath)

    if err != nil {

        log.Fatal(err)

    }

    defer f.Close()

    return get_sha256sum(f)

}


func get_sha256sum(r io.Reader) string {

    h := sha256.New()

    if _, err := io.Copy(h, r); err != nil {

        log.Fatal(err)

    }

    return fmt.Sprintf("%x", h.Sum(nil))

}


func main() {

    start := time.Now()

    ch := make(chan string, 10000)

    var wg sync.WaitGroup


    var get_fsha256sum_wrap = func(filepath string) {

        start := time.Now()

        ch <- get_fsha256sum(filepath)

        fmt.Printf("%f-%s\n", filepath, time.Since(start))

        wg.Done()

    }


    var walk_func = func(filepath string, info fs.DirEntry, err error) error {

        wg.Add(1)

        if err != nil {

            return err

        }

        if info.IsDir() {

            return nil

        }


        go get_fsha256sum_wrap(filepath)

        return nil


    }


    var over_wrap = func(root string) {

        filepath.WalkDir(root, walk_func)

        wg.Wait()

        close(ch)

    }

    go over_wrap("/run/media/user/Red/pictures_master/2021/01")

    for v := range ch {

        fmt.Println(v)

    }

    fmt.Printf("%s", time.Since(start))

}

错误信息:


fatal error: all goroutines are asleep - deadlock!


goroutine 1 [chan receive]:

main.main()

    /home/user/go_phockup/main.go:66 +0x273


goroutine 18 [semacquire]:

sync.runtime_Semacquire(0xc0000b8018)

    /usr/local/go/src/runtime/sema.go:56 +0x45

sync.(*WaitGroup).Wait(0xc0000b8010)

    /usr/local/go/src/sync/waitgroup.go:130 +0x65

main.main.func3(0x4e3d3f, 0x2b)

    /home/go_phockup/main.go:62 +0x5e

created by main.main

    /home/user/go_phockup/main.go:65 +0x1bd

exit status 2

任何想法是什么问题?


GCT1015
浏览 79回答 1
1回答

繁星点点滴滴

您的候补组正在等待比您创建的更多的 goroutine。walk_func添加到 中,但可能会在不创建新的 goroutine 的情况下返回。替换为:wgvar walk_func = func(filepath string, info fs.DirEntry, err error) error{&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if info.IsDir() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return nil&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; go get_fsha256sum_wrap(filepath)&nbsp; &nbsp; &nbsp; &nbsp; return nil&nbsp; &nbsp; &nbsp; &nbsp; }
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go