谷歌go goroutine的中断模式(速度问题) [英] interrupt pattern for google go goroutine (speed issue)

查看:137
本文介绍了谷歌go goroutine的中断模式(速度问题)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我运行一个goroutine来增加一个计数器,这个计数器可以被命令行输入t \ n中断。



中选择语句,如果我选择使用 default:,则计数器变量 j 会前转。这对我来说似乎很正常。然而,如果我选择使用 case< -time.After(100 * time.Microsecond): ,计数器 j 仅在一秒内增加到60个左右,而不是10,000个。

事实上,无论我在 time.After()中输入什么值,我只能得到大约60Hz的速率运行通过选择语句。



为什么?

<$ p
fmt
os
字符串

$ b $时间


func main(){
message:= make(chan string)
check check_input(message)
work_loop(message)

$ b $ func work_loop(消息chan字符串){
// var j [] [] int
var j int
t0:= time.Now ()
循环:
用于{
select {
case msg:=< -message:
如果msg ==terminate{
/ /fmt.Println(\"end task)
t1:= time.Now()
fmt.Println(j)
fmt.Println(total duration:,t1.Sub( t0))
break循环
}
大小写< -time.After(100 * time.Microsecond):
//默认:
//在这里工作
j + = 1
fmt.Println(j)
break

}
}
//fmt.Println(\"exit work loop)
}

func check_input(msg chan string){
reader:= bufio.NewReader(os.Stdin )
for {
line,err:= reader.ReadString('\\\
')

if err!= nil {
//您可以在这里查看if err == io.EOF
break
}

if strings.TrimSpace(line)==t{
msg< - terminate
}
}
}


解决方案

它与 time.Timer 的精度有关。查看 time.After


$ b


[...]的文档相当于NewTimer(d).C。

time.NewTimer $ b


NewTimer创建一个新的Timer,它将在至少之后的频道上发送当前时间。持续时间d。

(强调我的)



原因是 NewTimer 委托给一个运行时(操作系统相关)定时器,使得这个定时器的行为依赖于底层操作系统(以及Go集成的实现)。通常,我的经验是,亚毫秒粒度对任何语言都没有良好的跨平台支持,尤其是在Windows XP上

I run a goroutine to increment a counter, which can be interrupted by command line input "t\n"

In the select statement, if I choose to use default:, the counter variable j flies forword. That seems normal to me.

However, if I choose to use case <-time.After(100*time.Microsecond):, the counter j only adds up to 60 or so in one second, instead of 10,000.

In fact no matter what value I put in time.After(), I only get about 60Hz rate running through the select statement.

Why?

package main
import (
    "bufio"
    "fmt"
    "os"
    "strings"
    "time"
)

func main() {
    message := make(chan string)
    go check_input(message)
    work_loop(message)
}

func work_loop(message chan string) {
    //var j [][]int
    var j int
    t0:=time.Now()
Loop:
    for {
        select {
        case msg := <-message:
            if msg == "terminate" {
                //fmt.Println("end task")
                t1:=time.Now()
                fmt.Println(j)
                fmt.Println("total duration:", t1.Sub(t0))
                break Loop
            }
        case <-time.After(100 * time.Microsecond):
        //default:
            //do work here          
            j += 1
            fmt.Println(j)
            break

        }
    }
    //fmt.Println("exit work loop")
}

func check_input(msg chan string) {
    reader := bufio.NewReader(os.Stdin)
    for {
        line, err := reader.ReadString('\n')

        if err != nil {
            // You may check here if err == io.EOF
            break
        }

        if strings.TrimSpace(line) == "t" {
            msg <- "terminate"
        }
    }
}

解决方案

It has to do with the precision of time.Timer. Looking at the documentation of time.After:

[...] It is equivalent to NewTimer(d).C.

and the documentation of time.NewTimer:

NewTimer creates a new Timer that will send the current time on its channel after at least duration d.

(emphasis mine)

The reason for this is that NewTimer delegates to a runtime (OS-dependent) timer,making the behavior of this timer dependent on the underlying OS (and the implementation of the Go integration).

In general, it is my experience that sub-millisecond granularity does not have good cross-platform support in any language, especially on Windows XP.

这篇关于谷歌go goroutine的中断模式(速度问题)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆