致命错误:所有 goroutine 都处于睡眠状态 - 死锁,使用通道

问题描述 投票:0回答:1

我收到死锁错误。我无法删除它。请让我知道我到底在哪里犯了错误

package main

import (
    "fmt"
    "sync"
)

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

    wg.Add(2)
    go func() {
        defer wg.Done()
        b := 42
        ch1 <- b
        fmt.Println("ch1", ch1)
        wg.Wait()
        close(ch1)
    }()
    value := <-ch1
    fmt.Println("value", value)

    go func() {
        fmt.Println("enter", value)
        defer wg.Done()
        ch2 <- value
        a := <-ch2
        fmt.Println("ch2", a)
        wg.Wait()
        close(ch2)
    }()
    wg.Wait()
}

我在等待组和通道关闭方面工作。没成功

go channel goroutine
1个回答
0
投票

WaitGroup 和 Channels 是同步的手段,它们的工作方式不同。两者同时使用会造成混乱。

  1. WaitGroup:它是一种机制,通过它我们可以阻塞当前的go 例程,直到所有任务都由其他 go 例程执行 完成

    • wg.Add(num):添加等待的任务数量。
    • wg.Done():它将任务数量减少一。
    • wg.Wait():保持当前的 go 例程,直到任务计数器减少到 0。
  2. 通道:它是跨 Go 例程的通信媒介。阅读 空通道将在写入时阻塞当前的 go 例程 已经满的通道也会阻塞当前的例程。写作 在同一个 go 例程中读取相同的通道会导致死锁。作为 一旦有东西被写入 go 通道,它就会等待被读取 在其他 go 通道内,如果不存在,程序将 僵局。不需要关闭通道,除非发送者 明确地想要传达没有更多的价值观 发送。在封闭的通道上发送会引起恐慌。

据我在上面的代码片段中的理解,您试图在第一个 go 例程中将值 42 发送到 ch1 上,然后想要在主 go 例程中读取它,然后在另一个 go 例程中的另一个通道 ch2 上传递读取值,然后最后在 main go 例程中阅读它。这是代码片段的修改版本,可以帮助您做到这一点。

package main

import (
    "fmt"
    "sync"
)

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

    wg.Add(2)
    go func() {
        defer wg.Done()
        b := 42
        ch1 <- b
        fmt.Println("ch1", ch1)
        close(ch1)
    }()
    value := <-ch1
    fmt.Println("value", value)

    go func() {
        fmt.Println("enter", value)
        defer wg.Done()
        ch2 <- value
        close(ch2)
    }()
    a := <-ch2
    fmt.Println("ch2", a)
    wg.Wait()
}
© www.soinside.com 2019 - 2024. All rights reserved.