vs无限循环,没有时间.Sleep()

时间:2019-04-25 23:22:30

标签: go goroutine

我有一个goroutine正在无限播放play()的某些音频。为了保持play()的生命,我让调用函数随后运行了无限循环。

出乎意料的是,准系统循环似乎并没有让该函数无限地发挥作用,而我对原因感到茫然。但是,如果我将一个简单的time.Sleep(time.Second)添加到for循环的主体中,它似乎可以无限运行。知道为什么吗?

可视化:

func PlaysForAFewSeconds() {
    go play()
    for {
    }
}

^播放了几秒钟,但从未中断

func PlaysForever() {
    go play()
    for {
        time.Sleep(time.Second)
    }
}

^永远玩。

我猜想这与play()的实现方式有关,但我希望这是一个普遍的问题,足以使人们认识到这种症状。 谢谢。

1 个答案:

答案 0 :(得分:0)

static async Task Main(string[] args) { var tasks = Enumerable.Range(0, 3).Select(x => Task.Run(() => { Counter(); })); await Task.WhenAll(tasks); Console.ReadLine(); } public static void Counter() { while (true) { for (int i = 0; i < 1000000; i++) { Console.WriteLine(i); } } } 生成的程序集是for { },其中jmp selfself指令的位置。换句话说,CPU将尽可能快地继续运行jmp指令。 CPU每秒可以运行 n 条指令,这是无用的jmp还是实际有用的指令都没关系。

这被称为“忙等待”或“旋转锁定”,并且此行为并非特定于Go。大多数(所有?)编程语言的行为都是这样。

此类循环有一些用途,但在Go中,它们通常可以用通道替换:

jmp

从通道(// Simulate a function that takes 1s to complete. func play(ch chan struct{}) { fmt.Println("play") time.Sleep(1 * time.Second) ch <- struct{}{} } func PlaysForAFewSeconds() { wait := make(chan struct{}) go play(wait) <-wait } func PlaysForever() { wait := make(chan struct{}) for { go play(wait) <-wait } } )读取的操作被阻止,并且不使用任何CPU。我使用了一个空的匿名结构,它看起来有点丑陋,因为它没有分配任何内存。