为什么运行某些goroutine需要time.sleep?

Dar*_*ren 26 go goroutine

在GO教程中,我们有这张幻灯片:Goroutines

package main

import (
    "fmt"
    "time"
)

func say(s string) {
    for i := 0; i < 5; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }
}

func main() {
    go say("world")
    say("hello")
}
Run Code Online (Sandbox Code Playgroud)

运行此代码会产生预期的结果("world"和"hello"可互换地写入屏幕5次).

但是,如果我们注释掉time.Sleep(因此,"time"导入的行)并再次运行程序,我们只剩 "hello"写入屏幕五次.

什么是如此重要time.Sleep才能使goroutine免于死亡?

Dan*_*iel 34

如果你删除了time.Sleep你不给say("world")goroutine一个机会跑.goroutine调度程序不是抢占式的.你的goroutines必须在另一个goroutine运行之前放弃控制.放弃控制的一种方法是运行time.Sleep.

如果time.Sleepsay函数中取出,则主goroutine运行5次而不放弃对辅助goroutine的控制,然后当say主程序从程序返回时退出,因为没有任何东西可以使程序保持活动状态.


Ric*_*777 9

因为goroutine调度程序不是抢占式的,所以你的goroutine必须在另一个goroutine运行之前放弃控制.放弃控制的一种方法是time.Sleep.另一种方式是runtime.Gosched().

这是修改为使用Gosched()的教程:http://play.golang.org/p/jQ9mlGYXXE

这是理解goroutines的有用教训.但是,试图直接控制调度程序绝对是一种反模式; 悲伤往往会随之而来.

相反,更多地考虑像沟通数字硬件的大块(状态机是一个很好的比喻).最好学习goroutine所基于的Communicating Sequential Processes模型.在基于CSP的设计中,每个goroutine都有自己的私有状态,并交换消息以与其他goroutine的状态进行交互.消息的传递会强制同步,调度程序使用该同步来确定哪些活动获取cpu时间以及将哪些内容放入等待队列.

当你以这种方式接近Go时,你可能永远不必担心调度程序内部.

  • 我用`runtime.Gosched()`得到的结果略有不同.我得到5:你好,4:世界.用`time.Sleep()`我得到5个. (2认同)