英文:
How to make a select case non-blocking in for loop without default
问题
我有这段代码。
func Start() bool {
for {
if checkSomthingIsTrue() {
if err := doSomthing(); err != nil {
continue
}
}
select {
case <-ctx.Done():
return true
}
}
}
如何使上述函数非阻塞,而不使用default:
case。
不使用default case的原因是它会一直占用100%的CPU。
答案:
我使用了time.Ticker来进行节流。
谢谢。
英文:
I have this piece of code.
func Start() bool {
for {
if checkSomthingIsTrue() {
if err := doSomthing(); err != nil {
continue
}
}
select {
case <-ctx.Done():
return true
}
}
}
How to make the above function non blocking without using default:
case.
reason to not use default case is because its eating up 100% CPU always.
Answer:
I have used time.Ticker to throttle
Thanks
答案1
得分: 6
这里存在一个基本误解。一个线程只能做两件事情:
-
一个线程可以阻塞,等待某些事情发生。
-
一个线程可以运行,使用 CPU。
如果一个线程从不阻塞,那么它将使用 100% 的可用 CPU。你无法使非阻塞代码使用少于 100% 的可用 CPU。
你有三个选项:
-
使用非阻塞代码,并接受 100% 的 CPU 使用率。
-
重新设计
checkSomthingIsTrue()
,使其使用通道,并可以放在select
块中。for { select { case <-ctx.Done(): return true case <-whenSomethingIsTrue(): if err := doSomthing(); err != nil { continue } } }
-
使用超时来限制循环,例如:
// 每 100ms 进行一次轮询。 const pollInterval = 100 * time.Millisecond for { select { case <-ctx.Done(): return true case <-time.After(pollInterval): if checkSomthingIsTrue() { if err := doSomthing(); err != nil { continue } } } }
还要注意,continue
没有意义,但这是另一个问题。
英文:
There is a fundamental misunderstanding here. A thread can do only two things:
-
A thread can block, waiting for something.
-
A thread can run, using CPU.
If a thread never blocks, then it uses 100% of the available CPU. You cannot make non-blocking code use less than 100% of the available CPU.
You have three options:
-
Use non-blocking code, and accept the 100% CPU usage.
-
Redesign
checkSomthingIsTrue()
so it uses a channel, and can be put inside theselect
block.for { select { case <-ctx.Done(): return true case <-whenSomethingIsTrue(): if err := doSomthing(); err != nil { continue } } }
-
Use a timeout to throttle the loop, for example:
// Poll every 100ms. const pollInterval = 100 * time.Millisecond for { select { case <-ctx.Done(): return true case <-time.After(pollInterval): if checkSomthingIsTrue() { if err := doSomthing(); err != nil { continue } } } }
Also note that continue
makes no sense, but that is a different issue.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论