如何进行可重新启动的线程安全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的访问,但这感觉有点麻烦。还有更简洁的选择吗?

解决方法

我认为在这里使用互斥锁是合理的,无法想到更简单的解决方案。

您只需要添加几行就可以了:

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
    })
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...