var timer *time.Timer
func A() {
timer.Stop() // cancel old timer
go B() // new timer
}
func B() {
timer = time.NewTimer(100 * time.Millisecond)
select {
case <- timer.C:
// do something for timeout, like change state
}
}
函数A和B都在不同的goroutine中。
假设A在一个RPC goroutine中,当应用程序收到RPC请求时,它会取消B中的旧计时器,并在另一个goroutine中启动一个新计时器。
医生说:
停止并不关闭通道,以防止从通道的读取不正确地继续。
那么,如何打破B中的选择来避免goroutine泄漏呢?
4条答案
按热度按时间qni6mghb1#
使用额外的独立抵消信号。既然已经有了select语句,那么另一个通道显然是一个选择:
注意,所有的A和B都在竞争计时器值,使用上面的代码,A不需要停止计时器,所以你不需要全局计时器,消除了竞争:
hzbexzde2#
除了上面的答案之外,如果您想一次取消所有等待者,可以使用自己的计时器机制封装该行为,该机制可以取消,在
After
通道中发送true或false,以告诉您是从取消还是超时中唤醒所有等待者。输出:
Playground链接:
https://play.golang.org/p/z8OscJCXTvD
t1qtbnec3#
我已经做了自己的实现,与良好的老回调和种族条件的保护:
cig3rfwq4#
另一种不使用独立抵消信号处理停止信号的方法是在定时器通道上使用
range
。