Goroutines过早进入休眠状态

huangapple go评论81阅读模式
英文:

Goroutines prematurely go asleep

问题

代码:

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确实不直观),所以我希望在这里能得到答案。

英文:

The code:

package main

import (
	&quot;fmt&quot;
	&quot;time&quot;
)

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

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

func b(link chan bool) {
	go func() {
		&lt;-link
		fmt.Println(&quot;A&quot;)
	}()
	go func() {
		&lt;-link
		fmt.Println(&quot;B&quot;)
	}()
}

This code does nothing in particular, I'm just trying to understand channels and goroutines. But something is wrong and goroutines are asleep after two loops and application crashes.

Let's analyze what it does - every one second message is send to link. Function b receives it in two places, so print A and B is called. So basically every one second A and B should appear in console. But for reasons unknown to me it doesn't happen, program prints A and B once, and then crashes.
I probably don't understand the concept well enough (golang is really unintuitive), so I hope I can get an answer here.

答案1

得分: 1

将内容翻译为中文:

向无缓冲通道发送数据只有在有一个 goroutine 从中接收时才会成功。对于前两次发送,有 goroutine 从 link 通道接收数据。但它们只接收一个值后就终止了,不再有任何 goroutine 从 link 接收数据,所以第三次发送到 link 的操作被阻塞。由于没有其他 goroutine 在运行,程序发生了死锁。

英文:

A channel send to an unbuffered channel will only succeed if there is a goroutine receiving from it. For the first two sends, there are goroutines receiving from the link channel. But they receive one value and terminate, and there are no longer any goroutines receiiving from link, so the third send to link blocks. Since there are no other goroutines running, program deadlocks.

答案2

得分: -1

你的代码中的主要问题是在函数b中通过link通道接收到第一个消息时,你会退出goroutine,因此你不会监听发布者。所以你需要"订阅"该通道。你可以使用range来实现:

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

它会持续监听通道,直到你关闭它:close(link),然后它会退出。

此外,你还可以使用forselect的组合来实现,具体描述在这里

英文:

The main problem in your code is when you receive a first message through link channel in function b - you exit the goroutine, so you do not listen to the publisher. So you need to "subscribe" to the channel. You can do it via range, like:

for _ = range link {
	fmt.Println(&quot;A&quot;)
}

It will listen to the channel until you close it: close(link), then it will exit.

Also, you can do it using for select combination, as it described here

huangapple
  • 本文由 发表于 2023年3月16日 02:30:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/75748770.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定