Goroutines with time.Sleep 工作,但 WaitGroup 导致错误 - 同步问题?

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

我正在尝试同步 2 个 goroutine,例如 gr1 和 gr2 交替运行。 为此,我使用 2 个通道来协调。

当我使用

time.Sleep
等待 goroutine 完成时,它工作正常,没有任何错误。

当我使用

sync.Waitgroup
等待 goroutine 时,它会引发死锁错误。

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0x14000002101?)
        /usr/local/go/src/runtime/sema.go:62 +0x2c
sync.(*WaitGroup).Wait(0x1027bd710)
        /usr/local/go/src/sync/waitgroup.go:116 +0x74

按时间编程。睡眠

去游乐场链接

package main

import (
    "fmt"
    "time"
)

func main() {

    ch1, ch2 := make(chan int, 1), make(chan int, 1)

    go f1(ch1, ch2)
    go f2(ch2, ch1)

    ch1 <- 1
    time.Sleep(time.Second * 1)
}

func f1(ch1, ch2 chan int) {
    for i := 1; i < 5; i++ {
        num := <-ch1
        fmt.Println("f1", num*i)
        ch2 <- num * i
    }
}

func f2(ch2, ch1 chan int) {
    for i := 1; i < 5; i++ {
        num := <-ch2
        fmt.Println("f2", num*i)
        ch1 <- num * i
    }
}

与 Waitgroup 一起编程

去游乐场链接

package main

import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup

func main() {

    ch1, ch2 := make(chan int), make(chan int)

    wg = sync.WaitGroup{}
    wg.Add(2)

    go f1(ch1, ch2)
    go f2(ch2, ch1)

    ch1 <- 1
    wg.Wait()
}

func f1(ch1, ch2 chan int) {
    for i := 1; i < 5; i++ {
        num := <-ch1
        fmt.Println("f1", num*i)
        ch2 <- num * i
    }
    wg.Done()
}

func f2(ch2, ch1 chan int) {
    for i := 1; i < 5; i++ {
        num := <-ch2
        fmt.Println("f2", num*i)
        ch1 <- num * i
    }
    wg.Done()
}

对于缓冲通道,不会有错误。

我想了解 waitgroup 所做的与 time.sleep 不同的事情。

谢谢

go asynchronous channel goroutine
1个回答
0
投票

在 waitgroup 示例中,您在

f2
func 和最后一次迭代中
ch1 <- num * i
尝试写入 ch1,而该通道没有可用的读取器,并且因为它是无缓冲通道:

来自无缓冲通道的接收在该通道上相应的发送完成之前进行同步。 (https://go.dev/ref/mem#chan

由于

f2
停在那条线上,它永远不会到达
wg.Done()
并且
wg.Wait
会引发死锁恐慌。

更改 f2 可以解决问题,同时还有更好的选择:

func f2(ch2, ch1 chan int) {
    for i := 1; i < 5; i++ {
        num := <-ch2
        fmt.Println("f2", num*i)
        if i < 4 {
            ch1 <- num * i
        }
    }
    wg.Done()
}
© www.soinside.com 2019 - 2024. All rights reserved.