背景
我在线上使用这个库的代码,在看该库的实现的时候,发现了不常见函数的使用场景, 提了一个issue,想知道为啥这么用。
func (agt *Aggregator) TryEnqueue(item interface{}) bool {
select {
case agt.eventQueue <- item:
return true
default:
if agt.option.Logger != nil {
agt.option.Logger.Warnf("Aggregator: Event queue is full and try reschedule")
}
runtime.Gosched() // 这个函数的作用是让当前goroutine让出CPU,好让其它的goroutine获得执行的机会。同时,当前的goroutine也会在未来的某个时间点继续运行。
// 过一会儿再次调度到这个携程,继续往下执行。要么入队成功,要么返回入队失败。
select {
case agt.eventQueue <- item:
return true // 入队成功
default:
if agt.option.Logger != nil {
agt.option.Logger.Warnf("Aggregator: Event queue is still full and %+v is skipped.", item)
}
return false // 入队失败
}
}
}
runtime.Gosched()
使用场景
这个函数的作用是让当前goroutine让出CPU,好让其它的goroutine获得执行的机会。同时,当前的goroutine也会在未来的某个时间点继续运行。
除了让出CPU,还可以通过自旋来等待一会。自旋的方式可以避免携程上下文的切换。
那么这样就会引出一个问题:什么时候该自旋,什么时候该让出当前携程? TODO ?
自旋锁的应用场景
// 附录2 自旋是自旋锁的行为,它通过忙等待,让线程在某段时间内一直保持执行,从而避免线程上下文的调度开销。自旋锁对于线程只会阻塞很短时间的场景是非常合适的
参考
1.go runtime.Gosched()函数解析 2.自旋锁的应用场景
原创文章转载请注明出处: runtime.Gosched()函数