使用 Golang Timer 的正确方式

栏目: Go · 发布时间: 7年前

内容简介:以下讨论只针对由按照但是如果之前程序已经从 channel 中接收过事件,那么上述

一、标准 Timer 的问题

以下讨论只针对由 NewTimer 创建的 Timer,因为这种 Timer 会使用 channel 来传递到期事件,而正确操作 channel 并非易事。

Timer.Stop

按照 Timer.Stop 文档 的说法,每次调用 Stop 后需要判断返回值,如果返回 false(表示 Stop 失败,Timer 已经在 Stop 前到期)则需要排掉(drain)channel 中的事件:

if !t.Stop() {
	<-t.C
}

但是如果之前程序已经从 channel 中接收过事件,那么上述 <-t.C 就会发生阻塞。可能的解决办法是借助 select 进行 非阻塞 排放(draining):

if !t.Stop() {
	select {
	case <-t.C: // try to drain the channel
	default:
	}
}

但是因为 channel 的发送和接收发生在不同的 goroutine,所以 存在竞争条件 (race condition),最终可能导致 channel 中的事件未被排掉。

以下就是一种有问题的场景,按时间先后顺序发生:

select...case <-t.C

Timer.Reset

按照 Timer.Reset 文档 的说法,要正确地 Reset Timer,首先需要正确地 Stop Timer。因此 Reset 的问题跟 Stop 基本相同。

二、使用 Timer 的正确方式

参考 Russ Cox 的回复( 这里这里 ),目前 Timer 唯一合理的使用方式是:

  • 程序始终在同一个 goroutine 中进行 Timer 的 Stop、Reset 和 receive/drain channel 操作
  • 程序需要维护一个状态变量,用于记录它是否已经从 channel 中接收过事件,进而作为 Stop 中 draining 操作的判断依据

如果每次使用 Timer 都要按照上述方式来处理,无疑是一件很费神的事。为此,我专门写了一个 Gogoodtimer 来解决标准 Timer 的问题。懒是一种美德 :-)


以上所述就是小编给大家介绍的《使用 Golang Timer 的正确方式》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

编码整洁之道

编码整洁之道

罗伯特·C.马丁 / 电子工业出版社 / 2012-8 / 59.00元

忍受各种不确定性及不间断的压力并能够获取成功的程序员有一个共通特征:他们都深度关注软件创建实践。他们都把软件看做一种工艺品。他们都是专家。在“鲍勃大叔”看来“专业”的程序员不仅应该具备专业的技能,更应该具备专业的态度,这也是本书阐述的核心。专业的态度包括如何用带着荣誉感、自尊、自豪来面对进行软件开发,如何做好并做得整洁,如何诚实地进行沟通和估算,如何透明并坦诚地面对困难做抉择,如何理解与专业知识相......一起来看看 《编码整洁之道》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具