我正在尝试使用 Go 的
time.Timer
来安排需要以正确的顺序运行的任务,精度约为半毫秒。这在 OSX 和 Linux 上工作得很好,但在 Windows 上每次都会失败。
以下代码演示了该问题。它设置 5 个定时器,第一个为 1 ms,第二个为 2 ms,...,最后一个为 5 ms。一旦定时器触发,它的编号就会被打印出来。在 OSX 和 Linux 上,这显然会产生“12345”作为输出,但在 Windows 上,数字或多或少是随机的(在 Win 7 和 Windows Server 2012 上测试)。
package main
import (
"fmt"
"time"
)
func main() {
var timer1, timer2, timer3, timer4, timer5 *time.Timer
timer1 = time.NewTimer(1 * time.Millisecond)
timer2 = time.NewTimer(2 * time.Millisecond)
timer3 = time.NewTimer(3 * time.Millisecond)
timer4 = time.NewTimer(4 * time.Millisecond)
timer5 = time.NewTimer(5 * time.Millisecond)
// should print 12345
for {
select {
case <-timer1.C:
fmt.Print("1")
case <-timer2.C:
fmt.Print("2")
case <-timer3.C:
fmt.Print("3")
case <-timer4.C:
fmt.Print("4")
case <-timer5.C:
fmt.Print("5")
case <-time.After(200 * time.Millisecond):
return // exit the program
}
}
}
我认为这种行为是由于 Go 1.6 中所做的更改(https://golang.org/doc/go1.6#runtime,第 4 段),其中 Windows 计时器精度从 1 毫秒降低到 16 毫秒,尽管它之前也应该以较短的间隔(大约 100 μs)发生。
有什么方法可以将全局 Windows 计时器精度重置回 1 毫秒,或者访问高分辨率计时器以使上面的示例正常工作?
从 Go 1.7 开始,计时器现在具有更高的分辨率,这个问题应该不会发生。
几年后...这个问题在 Go 1.18 上仍然出现。
如果我打印 select 语句的持续时间,我会得到 210 到 220 毫秒之间的时间,因此计时器(或通道通信中......)存在 10-20 毫秒的抖动
Golang 从操作系统中获取时间分辨率。这与版本无关。