【问题标题】:Golang concurrency deadlock [duplicate]Golang并发死锁[重复]
【发布时间】:2016-06-16 14:30:54
【问题描述】:

谁能帮我确定为什么在我编写的 Go 代码末尾出现死锁错误?该程序实际上运行正常,但出现死锁错误。我是编写并发代码的新手,因此非常感谢任何帮助。我省略了一些我知道不是问题的行,只是为了让它更快阅读。

func MoveWorksheets(worksheetList []string) {

var wg sync.WaitGroup

for _, worksheet := range worksheetList {

    wg.Add(1)

    go MoveFile(src, dst, wg)

    }

    wg.Wait()
}

func MoveFile(src, dst string, wg sync.WaitGroup) (err error) {

    defer wg.Done()

    sfi, err := os.Stat(src)
    if err != nil {
        return
    }
    if !sfi.Mode().IsRegular() {
        // cannot copy non-regular files (e.g., directories,
        // symlinks, devices, etc.)
        return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String())
    }
    dfi, err := os.Stat(dst)
    if err != nil {
        if !os.IsNotExist(err) {
            return
        }
    } else {
        if !(dfi.Mode().IsRegular()) {
            return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", dfi.Name(), dfi.Mode().String())
        }
        if os.SameFile(sfi, dfi) {
            return
        }
    }
    /*if err = os.Link(src, dst); err == nil {
        return
    }*/
    err = MoveFileContents(src, dst)
    return
}

func MoveFileContents(src, dst string) (err error) {

    merr := os.Rename(src, dst)

    if merr != nil {
        log.Fatal(merr)
    }

    return
}

【问题讨论】:

  • 堆栈跟踪应该向您显示您阻塞的位置。输出是什么?
  • 致命错误:所有 goroutine 都处于休眠状态 - 死锁! goroutine 1 [semacquire]: sync.runtime_Semacquire(0xc08200274c) C:/Go/src/runtime/sema.go:47 +0x2d sync.(*WaitGroup).Wait(0xc082002740) C:/Go/src/sync/waitgroup. go:127 +0xbb main.MoveWorksheets(0xc08200a400, 0x14, 0x20) C:/code/src/github.com/deisun/adminsorter/adminsorterc.go:162 +0x27 main.Run() C:/code/src/github .com/deisun/adminsorter/adminsorterc.go:40 +0xa6 main.main() C:/code/src/github.com/deisun/adminsorter/adminsorterc.go:26 +0x46
  • 顺便说一句,go vet 捕捉到了这个错误。

标签: go concurrency deadlock


【解决方案1】:

MoveFile 正在获取wg 的副本,因此您在不同的WaitGroups 上调用Wait() 和Done()。尝试将其作为指针传递。

【讨论】:

  • 哇,原来如此……非常感谢!我是个白痴,不敢相信我没有想到这一点。
【解决方案2】:

尝试传递wg 变量的引用,在您的代码中MoveFile 函数正在获取它自己的WaitGroup 副本。这就是它造成死锁的原因。

   func MoveWorksheets(worksheetList []string) {

        var wg sync.WaitGroup

        for _, worksheet := range worksheetList {

          wg.Add(1)

          go MoveFile(src, dst, &wg)

        }

        wg.Wait()
    }

    func MoveFile(src, dst string, wg *sync.WaitGroup) (err error) {

        defer wg.Done()

        sfi, err := os.Stat(src)
        if err != nil {
            return
        }
        if !sfi.Mode().IsRegular() {
            // cannot copy non-regular files (e.g., directories,
            // symlinks, devices, etc.)
            return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String())
        }
        dfi, err := os.Stat(dst)
        if err != nil {
            if !os.IsNotExist(err) {
                return
            }
        } else {
            if !(dfi.Mode().IsRegular()) {
                return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", dfi.Name(), dfi.Mode().String())
            }
            if os.SameFile(sfi, dfi) {
                return
            }
        }
        /*if err = os.Link(src, dst); err == nil {
            return
        }*/
        err = MoveFileContents(src, dst)
        return
    }

    func MoveFileContents(src, dst string) (err error) {

        merr := os.Rename(src, dst)

        if merr != nil {
            log.Fatal(merr)
        }

        return
    }

【讨论】:

    猜你喜欢
    • 2019-10-18
    • 2019-05-10
    • 1970-01-01
    • 2022-08-16
    • 2020-07-08
    • 2018-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多