【发布时间】:2020-08-11 11:15:48
【问题描述】:
如何以线程安全的方式进行延迟的、可重新启动的函数调用?这是一个非常常见的用例,例如,如果您想对某些更改做出反应,但频率不会超过 X 毫秒一次。
我能想到的代码是:
var t *time.Timer
func restartableDelayed() {
if t != nil {
t.Stop()
}
t = time.AfterFunc(time.Second, func() {
t = nil
// ...
// Do the stuff here
// ...
})
}
这里明显的问题是 t = nil 赋值是从另一个 goroutine 调用的,而不是初始赋值,这会受到竞争。
如何以适当的并发安全方式完成此操作?在这里我唯一能想到的是涉及一个互斥锁来同步对t的访问,但这感觉有点麻烦。还有更简洁的选项吗?
【问题讨论】:
-
如果之前已经调用过,但是超时没有过期,又发出了新的调用,你想怎么办?丢弃它?超时后排队吗?
-
是的,丢弃。因此
t.Stop()调用 -
您可能会发现 golang.org/x/time/rate 和 golang.org/x/sync/singleflight 很有趣。
标签: go concurrency