[英]Golang for select loop consumes 100% of cpu
我有一个需要加载的资源,然后才允许对其进行任何访问。 它还需要每分钟更新一次。
通道的长度为 1 struct{},因此如果资源尚未加载,则循环将被阻塞。
下面的这段代码开始使用我 100% 的 cpu,我尝试添加
time.Sleep(10 * time.Millisecond)
这使得应用程序cpu消耗下降到1%
我认为自动收报机将是定时收藏的更好选择。
任何想法为什么它会消耗 100% cpu 或任何更好的实现想法?
func (al *AsyncLoop) Run() {
go func() {
for {
select {
case <-al.chanFetchRequest:
if al.fetched == false {
al.fetchData()
} else if al.lastUpdated.Add(1*time.Minute).Unix() < time.Now().Unix() && al.fetching == false {
go al.fetchData()
}
al.chanFetchResponse <- struct{}{}
continue
default:
continue
}
}
}()
}
我认为你只是在有新数据时发布到 al.chanFetchRequest 所以我认为你必须一直从这个频道阅读。 向选择中添加代码可能会导致您获取数据,即使它没有更改或(更糟)在它加载之前。 为什么不,在正常情况下,每次获取数据时都花点时间,然后确保在再次获取数据之前等待了足够的时间。 像这样的东西:
var nextFetch time.Time
for {
select {
case <-al.chanFetchRequest:
if al.fetched == false {
al.fetchData()
nextFetch = time.Now().Add(1 * time.Minute)
} else if time.Now().After(nextFetch) {
al.fetchData()
nextFetch = time.Now().Add(1 * time.Minute)
}
al.chanFetchResponse <- struct{}{}
}
}
default
语句创建一个非阻塞无限循环,导致 100% 的 cpu 使用率。 当 case 的条件不满足时,循环进入默认的非阻塞无限循环。
删除default
将解决问题。 但是会有一个 linter 警告S1000: should use for range instead of for { select {} }
通知select
对单通道没有意义。
最终代码将是
for {
_ := <-al.chanFetchRequest
if al.fetched == false {
al.fetchData()
nextFetch = time.Now().Add(1 * time.Minute)
} else if time.Now().After(nextFetch) {
al.fetchData()
nextFetch = time.Now().Add(1 * time.Minute)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.