[英]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.