为什么goroutines会陷入僵局?

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

我遇到了这些错误

致命错误:所有 goroutine 都在休眠 - 死锁!

`goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc0000081e0?)
    C:/Program Files/Go/src/runtime/sema.go:71 +0x25
sync.(*WaitGroup).Wait(0x0?)
    C:/Program Files/Go/src/sync/waitgroup.go:118 +0x48
main.main()`

但是我使用同步Wait()等工具。怎么了?我的代码:

 package main

    import (
    "fmt"
    "sync"
    )

    func sender(id int, data []int, out chan<- [2]int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < len(data); i += 2 {
        out <- [2]int{data[i], data[i+1]}
    }
    }

    func service(in <-chan [2]int, c, d int, out chan<- int, wg *sync.WaitGroup) {
    defer wg.Done()
    for pair := range in {
        sum := pair[0] + pair[1]
        if sum >= c && sum <= d {
            out <- sum
        }
    }
     }

     func receiver(in <-chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    line := 1
    for sum := range in {
        fmt.Printf("Line %d: Received sum %d\n", line, sum)
        line++
    }
     }

    func main() {
    data1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    data2 := []int{11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
    data3 := []int{21, 22, 23, 24, 25, 26, 27, 28, 29, 30}
    data4 := []int{31, 32, 33, 34, 35, 36, 37, 38, 39, 40}

    c, d := 15, 50

    senderToService := make(chan [2]int, 10)
    serviceToReceiver := make(chan int, 10)

    var wg sync.WaitGroup

    // Start sender goroutines
    wg.Add(4)
    go sender(1, data1, senderToService, &wg)
    go sender(2, data2, senderToService, &wg)
    go sender(3, data3, senderToService, &wg)
    go sender(4, data4, senderToService, &wg)

    // Close senderToService channel once all senders are done
    go func() {
        wg.Wait()
        close(senderToService)
    }()

    // Start service goroutine
    wg.Add(1)
    go service(senderToService, c, d, serviceToReceiver, &wg)

    // Close serviceToReceiver channel once the service is done
    go func() {
        wg.Wait()
        close(serviceToReceiver)
    }()

    // Start receiver goroutine
    wg.Add(1)
    go receiver(serviceToReceiver, &wg)

    // Wait for all goroutines to finish
    wg.Wait()
    }

我使用单个 WaitGroup (wg) 来管理管道的三个独立阶段之间的同步: 发送阶段产生数据。 服务阶段处理数据。 接收器阶段消耗处理后的数据。 当我在主函数中调用 wg.Wait() 时,它会等待所有阶段的所有减量。通道 senderToService 和 serviceToReceiver 在等待 wg.Wait() 的匿名 goroutine 中关闭。那么根本原因在哪里以及如何解决它?

go message deadlock channel
1个回答
0
投票

问题在于应用程序使用单个等待组来等待三个不同的事件(发送者完成、服务完成、接收者完成)。 一种解决方法是将程序更改为三个等待组。 一个更简单的解决方法是消除不必要的等待组的使用。

func sender(id int, data []int, out chan<- [2]int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < len(data); i += 2 {
        out <- [2]int{data[i], data[i+1]}
    }
}

func service(in <-chan [2]int, c, d int, out chan<- int) {
    defer close(out)
    for pair := range in {
        sum := pair[0] + pair[1]
        if sum >= c && sum <= d {
            out <- sum
        }
    }
}

func receiver(in <-chan int) {
    line := 1
    for sum := range in {
        fmt.Printf("Line %d: Received sum %d\n", line, sum)
        line++
    }
}

func main() {
    data1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    data2 := []int{11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
    data3 := []int{21, 22, 23, 24, 25, 26, 27, 28, 29, 30}
    data4 := []int{31, 32, 33, 34, 35, 36, 37, 38, 39, 40}

    c, d := 15, 50

    senderToService := make(chan [2]int, 10)
    serviceToReceiver := make(chan int, 10)

    var wg sync.WaitGroup

    // Start sender goroutines
    wg.Add(4)
    go sender(1, data1, senderToService, &wg)
    go sender(2, data2, senderToService, &wg)
    go sender(3, data3, senderToService, &wg)
    go sender(4, data4, senderToService, &wg)
    go func() {
        wg.Wait()
        close(senderToService)
    }()

    go service(senderToService, c, d, serviceToReceiver)
    receiver(serviceToReceiver)

}
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.