为什么程序会被select中的频道阻塞?
Why the program blocks by the channel in the select?
package main
import (
"fmt"
)
type A struct{
exit chan bool
}
func (a *A) f(){
select{
//the routine process
//quit
case <- a.exit:
fmt.Println("-----over-----")
a.exit <- true
fmt.Println("+++++over++++++")
}
}
func main() {
a := A{}
go a.f()
a.exit = make(chan bool)
a.exit <- true
}
我想要 运行 多个 goroutines,我想让 main func 通知其他 goroutine 退出。
这是我的代码,但是select中的程序块,程序只输出“-----over-----”,没有“+++++over++++++”,代码有什么问题?感谢您的帮助。
你的程序阻塞是因为那是你写的,考虑这个操作顺序:
main
goroutine 启动 a.f
goroutine.
a.f
阻止尝试从 nil 通道读取 a.exit
。
main
将 a.exit
设置为无缓冲通道,a.f
现在被阻止从新通道读取,这是允许的。
main
将一个值写入 a.exit
并且 a.f
从 a.exit
读取值,这同步了 goroutines,下层现在被阻塞了。
a.f
现在阻止尝试写入未缓冲的 a.exit
,这将永远不会取消阻止,因为没有人会再次尝试从通道读取。
main
现在退出并导致所有其他 goroutines 退出,这可能发生在第 5 步之前。
所以你的程序从不输出 +++++over++++++
的原因是:
- 你的
a.f
goroutine 在 a.exit <- true
阻塞,因为没有其他 goroutine 会从通道读取这个值。
- 您的
main
goroutine 可能会在 a.f
完成工作之前退出并终止整个程序。
我想你问的是如何在 goroutine 完成后让 main 退出,这是最简单的例子:
package main
import (
"fmt"
)
type A struct {
exit chan struct{}
}
func (a *A) f() {
defer close(a.exit) // Close the chanel after f() finishes, closed channels yield the zero-value so <-a.exit will unblock
fmt.Println("+++++over++++++")
}
func main() {
a := A{}
go a.f()
a.exit = make(chan struct{})
<-a.exit
}
package main
import (
"fmt"
)
type A struct{
exit chan bool
}
func (a *A) f(){
select{
//the routine process
//quit
case <- a.exit:
fmt.Println("-----over-----")
a.exit <- true
fmt.Println("+++++over++++++")
}
}
func main() {
a := A{}
go a.f()
a.exit = make(chan bool)
a.exit <- true
}
我想要 运行 多个 goroutines,我想让 main func 通知其他 goroutine 退出。 这是我的代码,但是select中的程序块,程序只输出“-----over-----”,没有“+++++over++++++”,代码有什么问题?感谢您的帮助。
你的程序阻塞是因为那是你写的,考虑这个操作顺序:
main
goroutine 启动a.f
goroutine.a.f
阻止尝试从 nil 通道读取a.exit
。main
将a.exit
设置为无缓冲通道,a.f
现在被阻止从新通道读取,这是允许的。main
将一个值写入a.exit
并且a.f
从a.exit
读取值,这同步了 goroutines,下层现在被阻塞了。a.f
现在阻止尝试写入未缓冲的a.exit
,这将永远不会取消阻止,因为没有人会再次尝试从通道读取。main
现在退出并导致所有其他 goroutines 退出,这可能发生在第 5 步之前。
所以你的程序从不输出 +++++over++++++
的原因是:
- 你的
a.f
goroutine 在a.exit <- true
阻塞,因为没有其他 goroutine 会从通道读取这个值。 - 您的
main
goroutine 可能会在a.f
完成工作之前退出并终止整个程序。
我想你问的是如何在 goroutine 完成后让 main 退出,这是最简单的例子:
package main
import (
"fmt"
)
type A struct {
exit chan struct{}
}
func (a *A) f() {
defer close(a.exit) // Close the chanel after f() finishes, closed channels yield the zero-value so <-a.exit will unblock
fmt.Println("+++++over++++++")
}
func main() {
a := A{}
go a.f()
a.exit = make(chan struct{})
<-a.exit
}