Go 使用vs进行无限循环而没有时间。Sleep()

Go 使用vs进行无限循环而没有时间。Sleep(),go,goroutine,Go,Goroutine,我有一个goroutine可以无限播放一些音频play()。为了使play()保持活动状态,我让调用函数在之后运行一个无限for循环 出乎意料的是,一个赤裸裸的循环似乎不能让函数无限发挥作用,我不知道为什么。但是,如果我在for循环的主体中添加一个简单的time.Sleep(time.Second),它似乎无限运行。你知道为什么吗 要可视化: func PlaysForAFewSeconds() { go play() for { } } ^播放几秒钟,但从不爆发 fu

我有一个goroutine可以无限播放一些音频
play()
。为了使
play()
保持活动状态,我让调用函数在之后运行一个无限for循环

出乎意料的是,一个赤裸裸的循环似乎不能让函数无限发挥作用,我不知道为什么。但是,如果我在for循环的主体中添加一个简单的
time.Sleep(time.Second)
,它似乎无限运行。你知道为什么吗

要可视化:

func PlaysForAFewSeconds() {
    go play()
    for {
    }
}
^播放几秒钟,但从不爆发

func PlaysForever() {
    go play()
    for {
        time.Sleep(time.Second)
    }
}
^永远演奏

我猜这与
play()
的实现方式有关,但我希望这是一个足够常见的问题,有人能认识到这种症状。
谢谢。

为{}生成的程序集是
jmp self
,其中
self
jmp
指令的位置。换句话说,CPU将尽可能快地运行
jmp
指令。CPU每秒可以运行n条指令,不管这是无用的
jmp
指令还是实际有用的指令

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

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

// 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
    }
}
//模拟一个需要1s才能完成的函数。
func play(ch chan结构{}){
fmt.Println(“播放”)
时间。睡眠(1*时间。秒)

ch为{}执行
的程序集
生成的是
jmp-self
,其中
self
jmp
指令的位置。换句话说,CPU将尽可能快地运行
jmp
指令。CPU每秒可以运行n条指令,这是无用的
jmp
指令还是实际有用的指令并不重要行动

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

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

// 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
    }
}
//模拟一个需要1s才能完成的函数。
func play(ch chan结构{}){
fmt.Println(“播放”)
时间。睡眠(1*时间。秒)

ch“为了保持play()的活动性,我让调用函数在之后运行一个无限for循环。”---这显然是错误的。启动goroutine后,它与调用它的代码没有任何连接。任何类型的循环都没有任何意义。如果
play()
是阻塞,只是在没有goroutines的情况下运行它。我同意这是一个糟糕的代码,但它没有提供任何关于goroutine根据for-loop主体的不同行为的见解。有多少cpu可用于进程?使用什么go版本?是否在任何地方手动设置
runtime.GOMAXPROCS
?4个cpu,而不是m正在使用runtime.GOMAXPROCS。繁忙循环总是一个编程错误。即使调度程序可能会中断它,它也没有用,并且会浪费cpu。请不要这样做。“为了保持play()活动,我让调用函数在之后运行无限for循环。”---这是完全错误的。启动goroutine后,它与调用它的代码没有任何连接。任何类型的循环都没有意义。如果
play()
是阻塞,只是在没有goroutines的情况下运行它。我同意这是一个糟糕的代码,但它没有提供任何关于goroutine根据for-loop主体的不同行为的见解。有多少cpu可用于进程?使用什么go版本?是否在任何地方手动设置
runtime.GOMAXPROCS
?4个cpu,而不是m正在使用runtime.GOMAXPROCS。繁忙的循环总是一个编程错误。即使调度程序可以中断它,它也没有用,并且浪费了cpu。只是不要这样做。我相信最初的问题是关于“它到底为什么会发生”。一个有用的“繁忙等待”或“旋转锁”实际上是在检查一些条件。空的
jmp self
没有真正的用途。我相信最初的问题是关于“它到底为什么会发生”。有用的“忙等待”或“旋转锁”实际上是在检查一些条件。空的
jmp self
没有真正的用途。