问题描述
如何以线程安全的方式进行延迟的,可重新启动的函数调用?例如,如果您想对某些更改做出反应,但这种情况很常见,但不超过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
的访问,但这感觉有点麻烦。还有更简洁的选择吗?
解决方法
我认为在这里使用互斥锁是合理的,无法想到更简单的解决方案。
您只需要添加几行就可以了:
var (
mu sync.Mutex
t *time.Timer
)
func restartableDelayed() {
mu.Lock()
defer mu.Unlock()
if t != nil {
t.Stop()
}
t = time.AfterFunc(time.Second,func() {
mu.Lock()
t = nil
mu.Unlock()
// Do the stuff here
})
}