IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    关于Go协程调度的一个小问题

    Xiang Chao (cloudaice@163.com)发表于 2015-01-13 00:00:00
    love 0

    根据官方文档的描述,用Go语言编写的程序在运行的时候,对协程的调度是不确定的。也就是说某一个时间里,具体哪个协程在运行是不确定的。但是下面出现了一个反例:

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        c := make(chan string)
        done := make(chan struct{})
        go feed("cat", c, done)
        go feed("dog", c, done)
        c <- "fish"
        <-done
    }
    
    func feed(name string, ch chan string, done chan struct{}) {
        meat := <-ch
        fmt.Println(name, "eat", meat)
        done <- struct{}{}
    }
    

    运行上面这段代码输出的总是cat eat fish。也就是说,每次都是cat那个协程可以拿到通道中的数据。而不是cat和dog随机从通道中拿到数据。这个现象和官方的描述是有出入的。但是对这段代码稍作改动,每次运行的时候,出现的结果就会是随机的,且看下面这段代码:

    package main
    
    import (
        "fmt"
        "runtime"
    )
    
    func init() {
        runtime.GOMAXPROCS(runtime.NumCPU() * 2)
    }
    
    func main() {
        c := make(chan string)
        done := make(chan struct{})
        go feed("cat", c, done)
        go feed("dog", c, done)
        c <- "fish"
        <-done
    }
    
    func feed(name string, ch chan string, done chan struct{}) {
        meat := <-ch
        fmt.Println(name, "eat", meat)
        done <- struct{}{}
    }
    

    这段代码在运行的时候,基本上dog eat fish和cat eat fish是随机出现的。符合官方对协程调度的描述。

    分析

    第二段代码中,增加了runtime.GOMAXPROCS,设置了最大的Process的数量。换句话说,就是允许多个 Process来调度协程。这个时候,cat和dog两个协程就是随机从通道中获取到数据。因此,在默认协程数量为1的时候,先启动的协程似乎优先拥有时间片,但是这还需要阅读标准库中的源代码进行确认。



沪ICP备19023445号-2号
友情链接