首页 文章

选择默认 Channels 竞争条件

提问于
浏览
2

https://play.golang.org/p/FMKxtVlTL5

为什么select语句中的 default: 无限循环程序?

package main

import (
    "fmt"
    "strconv"
    "time"
)

var quit chan bool
var counter chan int

func main() {
    counter = make(chan int)
    quit = make(chan bool)
    go func() {
        i := 0
        for {
            i++
            select {
            case <-quit:
                fmt.Println("Bye!")
                return
            case counter <- i:
                fmt.Println("Send! " + strconv.Itoa(i))
            default:
                fmt.Println("Default! " + strconv.Itoa(i))
            }
        }
    }()
    fmt.Println("Receive! " + strconv.Itoa(<-counter))
    fmt.Println("Receive! " + strconv.Itoa(<-counter))
    fmt.Println("Receive! " + strconv.Itoa(<-counter))
    fmt.Println("Receive! " + strconv.Itoa(<-counter))
    fmt.Println("Receive! " + strconv.Itoa(<-counter))
    fmt.Println("Receive! " + strconv.Itoa(<-counter))
    quit <- true
    time.Sleep(1 * time.Second)
}

1 回答

  • 6

    select 具有 default 时,它变为非阻塞 . 引用规范:

    如果一个或多个通信可以继续,则可以通过统一的伪随机选择来选择可以继续进行的单个通信 . 否则,如果存在默认情况,则选择该情况 . 如果没有默认情况,则“select”语句将阻塞,直到至少一个通信可以继续 .

    如果没有 defaultselect 将等到它可以从 quit 接收或发送 counter ,执行此操作,然后继续(再次通过 for 循环,除非它运行 return ) . 在默认情况下, select 永远不会等待任何事情, default 只是每次都可以运行,除非其他操作之一通过 .

    从理论上讲,程序仍然可以正常工作,并在第六次打印“发送”后退出 . 和“接收!” - 但它可能太忙了打印“默认!”几十亿次在合理的时间到达那里 .

相关问题