在带有select case和default的GOROUTIES中,一旦通道关闭,default将不会执行
我试图理解默认情况下select块中闭合通道的行为,但对以下输出感到困惑。 这里我调用50个goroutine并关闭finish通道在带有select case和default的GOROUTIES中,一旦通道关闭,default将不会执行,go,Go,我试图理解默认情况下select块中闭合通道的行为,但对以下输出感到困惑。 这里我调用50个goroutine并关闭finish通道 func testClosedChannelBehavior() { const n = 50 finish := make(chan bool) var done sync.WaitGroup for i := 0; i < n; i++ { done.Add(1) go func(x int
func testClosedChannelBehavior() {
const n = 50
finish := make(chan bool)
var done sync.WaitGroup
for i := 0; i < n; i++ {
done.Add(1)
go func(x int) {
select {
case <-time.After(1 * time.Hour):
case <-finish:
fmt.Printf("received finish %d\n", x)
default:
fmt.Printf("I didnt wait %d\n", x)
}
done.Done()
}(i)
}
t0 := time.Now()
close(finish)
fmt.Println("finish closed")
done.Wait()
fmt.Printf("Waited %v for %d goroutines to stop\n", time.Since(t0), n)
}
func testClosedChannelBehavior(){
常数n=50
完成:=制作(陈波)
var done sync.WaitGroup
对于i:=0;i 对fmt.Printf的case调用涉及一个syscall。Syscalls会自动导致该goroutine被重新调度,因为它必须等待操作系统完成该syscall。这意味着其中一些goroutine很可能运行select语句并选择默认的case,但还不能打印到控制台
编辑:此外,如果您在具有多个线程的系统上运行此程序,默认情况下,go运行时将并行运行多个go例程(与操作系统线程数匹配),这意味着其中一些goroutine可能与通道关闭同时执行,并在主goroutine中发生通道关闭之前到达select语句
如果您添加同步通道,以确保通道关闭操作在任何Goroutine中的select
发生之前进行,则它将按预期工作:
func testClosedChannelBehavior(){
常数n=50
完成:=制作(陈波)
继续:=make(chan结构{})
var done sync.WaitGroup
对于i:=0;i 对fmt.Printf的调用涉及一个syscall。Syscalls会自动导致该goroutine被重新调度,因为它必须等待操作系统完成该syscall。这意味着其中一些goroutine很可能运行select语句并选择默认情况,但还不能打印到控制台
编辑:此外,如果您在具有多个线程的系统上运行此程序,默认情况下,go运行时将并行运行多个go例程(与操作系统线程数匹配),这意味着其中一些goroutine可能与通道关闭同时执行,并在主goroutine中发生通道关闭之前到达select语句
如果您添加同步通道,以确保通道关闭操作在任何Goroutine中的select
发生之前进行,则它将按预期工作:
func testClosedChannelBehavior(){
常数n=50
完成:=制作(陈波)
继续:=make(chan结构{})
var done sync.WaitGroup
对于i:=0;i 感谢@Kaedys的快速响应。将接受此作为答案。同步通道是一个干净的修复:)…感谢@Kaedys的快速响应。将接受此作为答案。同步通道是一个干净的修复:)。。。
func testClosedChannelBehavior() {
const n = 50
finish := make(chan bool)
proceed := make(chan struct{})
var done sync.WaitGroup
for i := 0; i < n; i++ {
done.Add(1)
go func(x int) {
<-proceed
select {
case <-time.After(1 * time.Hour):
case <-finish:
fmt.Printf("received finish %d\n", x)
default:
fmt.Printf("I didnt wait %d\n", x)
}
done.Done()
}(i)
}
t0 := time.Now()
close(finish)
fmt.Println("finish closed")
close(proceed)
done.Wait()
fmt.Printf("Waited %v for %d goroutines to stop\n", time.Since(t0), n)
}