为什么所有的 goroutine 都睡着了——死锁。识别瓶颈

package main


import (

    "fmt"

    "runtime"

    "sync"

    "time"

)


func main() {

    intInputChan := make(chan int, 50)

    var wg sync.WaitGroup

    for i := 0; i < 3; i++ {

        wg.Add(1)

        go worker(intInputChan, wg)

    }

    for i := 1; i < 51; i++ {

        fmt.Printf("Inputs. %d \n", i)

        intInputChan <- i

    }

    close(intInputChan)

    wg.Wait()

    fmt.Println("Existing Main App... ")

    panic("---------------")

}


func worker(input chan int, wg sync.WaitGroup) {

    defer func() {

        fmt.Println("Executing defer..")

        wg.Done()

    }()


    for {

        select {

        case intVal, ok := <-input:

            time.Sleep(100 * time.Millisecond)

            if !ok {

                input = nil

                return

            }

            fmt.Printf("%d  %v\n", intVal, ok)


        default:

            runtime.Gosched()

        }

    }


}

抛出的错误是。


致命错误:所有 goroutine 都处于睡眠状态 - 死锁!


goroutine 1 [semacquire]:sync.(*WaitGroup).Wait(0xc082004600) c:/go/src/sync/waitgroup.go:132 +0x170 main.main() E:/Go/go_projects/go/src/Test .go:22 +0x21a


四季花海
浏览 223回答 2
2回答

元芳怎么了

我刚刚尝试过(操场)通过 awg *sync.WaitGroup并且它有效。传递sync.WaitGroup意味着传递sync.WaitGroup(按值传递)的副本:goroutine 提到Done()了不同的 sync.WaitGroup.var wg sync.WaitGroupfor i := 0; i < 3; i++ {&nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; go worker(intInputChan, &wg)}请注意&wg:您正在按值传递指向原始 的指针sync.WaitGroup,供 goroutine 使用。

倚天杖

如所提到的,不从同步绕包传值的类型,右靠近的顶部sync包文档:“含有在此包中定义的类型的值不应该被复制。&nbsp;”这也包括类型本身(sync.Mutex,sync.WaitGroup等)。但是,有几个注意事项:wg.Add如果您知道要添加多少个,您可以只使用一次调用(但如文档所示,请确保在任何调用之前都已完成Wait)。你不想那样打电话runtime.Gosched;它使工人忙循环。您可以使用range从通道读取以简化在关闭时停止的过程。对于小函数,您可以使用闭包,而根本不需要传递通道或等待组。这变成了这样:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "sync"&nbsp; &nbsp; "time")func main() {&nbsp; &nbsp; const numWorkers = 3&nbsp; &nbsp; c := make(chan int, 10)&nbsp; &nbsp; var wg sync.WaitGroup&nbsp; &nbsp; wg.Add(numWorkers)&nbsp; &nbsp; for i := 0; i < numWorkers; i++ {&nbsp; &nbsp; &nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defer func() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Executing defer…")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for v := range c {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("recv:", v)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(100 * time.Millisecond)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }()&nbsp; &nbsp; }&nbsp; &nbsp; for i := 1; i < 51; i++ {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("send:", i)&nbsp; &nbsp; &nbsp; &nbsp; c <- i&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println("closing…")&nbsp; &nbsp; close(c)&nbsp; &nbsp; fmt.Println("waiting…")&nbsp; &nbsp; wg.Wait()&nbsp; &nbsp; fmt.Println("Exiting Main App... ")}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go