英文:
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 (
"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")
}()
}
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)
,然后它会退出。
此外,你还可以使用for
和select
的组合来实现,具体描述在这里。
英文:
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("A")
}
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论