在繁忙的循环中休眠 goroutine
Sleep in goroutine with busy loop
我在 goroutine 中有一个 switch 语句来处理音频的播放状态。 switch 语句看起来像这样(它由通道控制)
PlaybackLoop:
// Poll playback status and update current song
select {
case <-next:
if current.next != nil {
current = current.next
break PlaybackLoop
}
case <-prev:
if current.prev != nil {
current = current.prev
}
break PlaybackLoop
case <-done:
return err
default:
time.Sleep(50 * time.Millisecond)
当没有通道有输入时,default
情况 sleep
持续 50 毫秒。我这样做的理由是我不会不必要地刷新 UI 或检查媒体状态等(在 switch 语句之前的 PlayBackLoop
中发生的事情)。
是 休眠 并且是使 goroutine 更高效的适当方法吗? (通过减少对媒体播放器状态的检查?)或者这个假设是完全没有根据的,一个简单的 continue
就足够了吗?
使用对 time.Sleep
的调用绝不是协调并发进程的正确选择,最好尽可能依赖同步原语和运行时来协调并发。
在这种情况下,您似乎正在轮询一个事件,睡眠是为了防止您 运行 一个繁忙的循环,这只会浪费 cpu 并可能饿死其他 goroutines/threads 共 CPU。
如果您无法避免轮询某个事件,那么您可以通过使用 time.Ticker
使轮询间隔更加一致来稍微改进一下。
ticker := time.NewTicker(pollInterval)
defer ticker.Stop()
PlaybackLoop:
for {
select {
case <-next:
if current.next != nil {
current = current.next
break PlaybackLoop
}
case <-prev:
if current.prev != nil {
current = current.prev
}
break PlaybackLoop
case <-done:
return err
case <-ticker.C:
pollForEvent()
}
}
我在 goroutine 中有一个 switch 语句来处理音频的播放状态。 switch 语句看起来像这样(它由通道控制)
PlaybackLoop:
// Poll playback status and update current song
select {
case <-next:
if current.next != nil {
current = current.next
break PlaybackLoop
}
case <-prev:
if current.prev != nil {
current = current.prev
}
break PlaybackLoop
case <-done:
return err
default:
time.Sleep(50 * time.Millisecond)
当没有通道有输入时,default
情况 sleep
持续 50 毫秒。我这样做的理由是我不会不必要地刷新 UI 或检查媒体状态等(在 switch 语句之前的 PlayBackLoop
中发生的事情)。
是 休眠 并且是使 goroutine 更高效的适当方法吗? (通过减少对媒体播放器状态的检查?)或者这个假设是完全没有根据的,一个简单的 continue
就足够了吗?
使用对 time.Sleep
的调用绝不是协调并发进程的正确选择,最好尽可能依赖同步原语和运行时来协调并发。
在这种情况下,您似乎正在轮询一个事件,睡眠是为了防止您 运行 一个繁忙的循环,这只会浪费 cpu 并可能饿死其他 goroutines/threads 共 CPU。
如果您无法避免轮询某个事件,那么您可以通过使用 time.Ticker
使轮询间隔更加一致来稍微改进一下。
ticker := time.NewTicker(pollInterval)
defer ticker.Stop()
PlaybackLoop:
for {
select {
case <-next:
if current.next != nil {
current = current.next
break PlaybackLoop
}
case <-prev:
if current.prev != nil {
current = current.prev
}
break PlaybackLoop
case <-done:
return err
case <-ticker.C:
pollForEvent()
}
}