如何进行可重新启动、线程安全的 AfterFunc() 调用

如何以线程安全的方式进行延迟的、可重新启动的函数调用?这是一个非常常见的用例,例如,如果您想对某些更改做出反应,但频率不会超过 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,但这感觉有点麻烦。还有更简洁的选择吗?


慕尼黑的夜晚无繁华
浏览 104回答 1
1回答

白衣非少年

我认为在这里使用互斥锁是合理的,想不出更简单的解决方案。你只需要添加几行就可以了: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    })}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go