致命错误:所有goroutine都处于休眠状态-死锁|围棋套路

m1m5dgzv  于 2023-01-28  发布在  Go
关注(0)|答案(1)|浏览(117)

问题是goOne和goTwo函数都在分别向通道ch1和ch2发送值,但是main函数中没有这些值的对应接收器,这意味着通道被阻塞,程序无法继续,结果main函数中的select语句无法从通道中读取,因此总是执行默认情况。

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    ch1 := make(chan string)
    ch2 := make(chan string)

    wg.Add(2)
    go goOne(&wg, ch1)
    go goTwo(&wg, ch2)

    select {
    case <-ch1:
        fmt.Println(<-ch1)
        close(ch1)

    case <-ch2:
        fmt.Println(<-ch2)
        close(ch2)

    default:
        fmt.Println("Default Case")
    }
    wg.Wait()

}

func goTwo(wg *sync.WaitGroup, ch2 chan string) {
    ch2 <- "Channel 2"
    wg.Done()
}

func goOne(wg *sync.WaitGroup, ch1 chan string) {
    ch1 <- "Channel 1"
    wg.Done()
}

输出:

Default Case
fatal error: all goroutines are asleep - deadlock!

goroutine 1 \[semacquire\]:
sync.runtime_Semacquire(0xc000108270?)
/usr/local/go/src/runtime/sema.go:62 +0x25
sync.(\*WaitGroup).Wait(0x4b9778?)
/usr/local/go/src/sync/waitgroup.go:139 +0x52
main.main()
/home/nidhey/Documents/Go_Learning/goroutines/select.go:29 +0x2af

goroutine 6 \[chan send\]:
main.goOne(0x0?, 0x0?)
/home/nidhey/Documents/Go_Learning/goroutines/select.go:39 +0x28
created by main.main
/home/nidhey/Documents/Go_Learning/goroutines/select.go:14 +0xc5

goroutine 7 \[chan send\]:
main.goTwo(0x0?, 0x0?)
/home/nidhey/Documents/Go_Learning/goroutines/select.go:33 +0x28
created by main.main
/home/nidhey/Documents/Go_Learning/goroutines/select.go:15 +0x119\```

我正在寻找一个不同的模式,如选择处理的情况下,通道被封锁。
为了解决这个问题,我在main函数的wg.wait()后面添加了一个〈-ch1或〈-ch2,以接收发送到通道的值并解除阻塞

tjjdgumg

tjjdgumg1#

我们并不完全清楚自己想做什么,如果你想等待两个goroutine完成工作,并把它们的工作结果输入通道,那么你就不需要权重组(因为它不会被访问)。
你可以做这样的事。

package main

import (
    "fmt"
    "time"
)

func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)

    go goOne(ch1)
    go goTwo(ch2)

    for {
        select {
        case v := <-ch1:
            fmt.Println("Done ch1:", v)
            ch1 = nil
        case v := <-ch2:
            fmt.Println("Done ch2:", v)
            ch2 = nil
        case <-time.After(time.Second):
            fmt.Println("I didn't get result so lets skip it!")
            ch1, ch2 = nil, nil
        }
        if ch1 == nil && ch2 == nil {
            break
        }
    }
}

func goTwo(ch chan string) {
    ch <- "Channel 2"
}

func goOne(_ chan string) {
    //ch1 <- "Channel 1"
}

相关问题