选择默认频道竞争条件

时间:2016-06-04 17:56:13

标签: go

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 个答案:

答案 0 :(得分:6)

selectdefault时,它会变为非阻塞状态。引用规范:

  

如果一个或多个通信可以继续,则可以通过统一的伪随机选择来选择可以继续的单个通信。否则,如果存在默认情况,则选择该情况。如果没有默认情况,&#34;选择&#34;语句阻塞,直到至少有一个通信可以继续。

如果没有defaultselect会等到它可以从quit接收或发送counter,然后继续(通过for 1}}再次循环,除非它运行return)。 使用默认值,select永远不会等待任何内容,default只会在每次运行时运行,除非其他操作之一通过。

理论上程序仍然有效,并且会在第六次打印后退出&#34;发送!&#34;和&#34;接收!&#34; - 但它可能太忙了打印&#34;默认!&#34;几十亿次在合理的时间内到达那里。