Goroutine会过早地进入睡眠状态

dm7nw8vv  于 2023-03-21  发布在  Go
关注(0)|答案(2)|浏览(129)

代码:

package main

import (
    "fmt"
    "time"
)

func main() {
    link := make(chan bool)
    stop := make(chan bool)
    go a(link, stop)
    go b(link)
    <-stop
}

func a(link chan bool, stop chan bool) {
    for i := 0; i < 20; i++ {
        time.Sleep(1 * time.Second)
        link <- true
    }
    stop <- true
}

func b(link chan bool) {
    go func() {
        <-link
        fmt.Println("A")
    }()
    go func() {
        <-link
        fmt.Println("B")
    }()
}

这段代码没有做什么特别的事情,我只是试图理解通道和goroutine,但是出了问题,goroutine在两次循环和应用程序崩溃后就休眠了。
让我们分析一下它的功能--每隔一秒,消息就会发送到link。函数b在两个地方接收消息,因此调用了print A和B。因此,基本上每隔一秒,A和B就会出现在控制台中。但由于我不知道的原因,它没有出现,程序打印A和B一次,然后崩溃。我可能对这个概念理解得不够好(golang真的很不直观),所以我希望我能在这里得到一个答案。

ijxebb2r

ijxebb2r1#

只有当goroutine从一个无缓冲的通道接收数据时,通道发送才会成功,在前两次发送中,有goroutine从link通道接收数据,但是它们只接收到一个值就终止了,并且不再有goroutine从link接收数据,所以第三次发送link会阻塞,因为没有其他goroutine在运行,程序就会死锁。

j7dteeu8

j7dteeu82#

你的代码中的主要问题是,当你在b函数中通过link通道接收到一个first消息时,你exitgoroutine,这样你就不会监听发布者,所以你需要“subscribe”这个通道,你可以通过range来实现,比如:

for _ = range link {
    fmt.Println("A")
}

它将监听频道,直到您关闭它:close(link),则它将退出。
此外,您还可以使用forselect组合来执行此操作,如here所述

相关问题