草庐IT

超时 Goroutine 的 Golang 间歇性行为

coder 2024-07-13 原文

我正在尝试为重复性任务实现并发。我想在不同的 Goroutine 上实现一个 http 请求(如 longRunningTask 函数所示)。我为停止 Goroutine 的机制提供了一个计时器,并在重负载任务进行到预定义的超时时向主 Goroutine 发送超时信号。我目前遇到的问题是我出现间歇性行为。

代码已简化为如下所示。

package main

import (
    "fmt"
    "time"
)

func main() {
    var iteration int = 5

    timeOutChan := make(chan struct{})
    resultChan := make(chan string)

    for i := 0; i < iteration; i++ {
        go longRunningTaks(timeOutChan, resultChan)
    }

    for i := 0; i < iteration; i++ {
        select {
        case data := <-resultChan:
            fmt.Println(data)
        case <-timeOutChan:
            fmt.Println("timed out")
        }
    }

}

func longRunningTaks(tc chan struct{}, rc chan string) {
    timer := time.NewTimer(time.Nanosecond * 1)
    defer timer.Stop()

    // Heavy load task
    time.Sleep(time.Second * 1)

    select {
    case <-timer.C:
        tc <- struct{}{}
    case rc <- "success":
        return
    }
}

我相信每次尝试都应该打印出来

timeout
timeout
timeout
timeout
timeout

相反,我得到了间歇性的

success
timeout
timeout
timeout
timeout

最佳答案

文档提到:

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

“至少意味着”计时器肯定会花费指定的时间,但这也隐含地意味着可以花费比指定时间更多的时间。计时器开始自己的 go 例程并在到期时写入 channel 。 由于调度程序或垃圾收集或写入其他 channel 的过程可能会延迟。此外,考虑到上述可能性,模拟工作量非常短。

更新:

正如 Peter 在评论中提到的那样,将“成功”写入 rc channel 是同样可能完成的操作,因为主例程可以从另一端读取该操作。选择必须在 1) 将“成功”写入 rc channel 和 2) 超时计时器之间进行选择。两者都是可能的。 No1 的可能性在开始时更大,因为主例程尚未从另一端读取它。一旦发生这种情况。其他剩余的例程将不得不竞争 channel (写入“成功”)(因为它在缓冲区大小为 0 时阻塞)所以对于其余时间,过期计时器被选中的可能性更大不能说主例程从 resultChan channel (rc 的另一端)读取的速度有多快。

关于超时 Goroutine 的 Golang 间歇性行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56966124/

有关超时 Goroutine 的 Golang 间歇性行为的更多相关文章

  1. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  2. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  3. ruby-on-rails - Rails 优雅地处理超时 session ? - 2

    使用rails4,ruby2。我在rails配置中为我的cookiesession设置了30分钟的超时时间。问题是,如果我转到表单,让session超时,然后提交表单,我会收到此ActionController::InvalidAuthenticityToken错误。如何在Rails中优雅地处理这个错误?比如说,重定向到登录屏幕? 最佳答案 在您的ApplicationController:rescue_fromActionController::InvalidAuthenticityTokendoredirect_tosome_p

  4. ruby - Ruby gsub 替换中的行为不一致? - 2

    两个gsub产生不同的结果。谁能解释一下为什么?代码也可在https://gist.github.com/franklsf95/6c0f8938f28706b5644d获得.ver=9999str="\tCFBundleDevelopmentRegion\n\ten\n\tCFBundleVersion\n\t0.1.190\n\tAppID\n\t000000000000000"putsstr.gsub/(CFBundleVersion\n\t.*\.).*()/,"#{$1}#{ver}#{$2}"puts'--------'putsstr.gsub/(CFBundleVersio

  5. ruby-on-rails - Ruby 中意外的大小写行为 - 2

    我在一段非常简单的代码(如我所想)中得到了一个错误的值:org=4caseorgwhenorg=4val='H'endputsval=>nil请不要生气,我希望我错过了一些非常明显的东西,但我真的想不通。谢谢。 最佳答案 这是典型的Ruby错误。case有两种被调用的方法,一种是你传递一个东西作为分支的基础,另一种是你不传递的东西。如果您确实在case中指定了一个表达式语句然后评估所有其他条件并与===进行比较.在这种情况下org评估为false和org===false显然不是真的。所有其他情况也是如此,它们要么是真的,要么是假的。

  6. ruby - 使对象的行为类似于 ruby​​ 中并行分配的数组 - 2

    假设您在Ruby中执行此操作:ar=[1,2]x,y=ar然后,x==1和y==2。是否有一种方法可以在我自己的类中定义,从而产生相同的效果?例如rb=AllYourCode.newx,y=rb到目前为止,对于这样的赋值,我所能做的就是使x==rb和y=nil。Python有这样一个特性:>>>classFoo:...def__iter__(self):...returniter([1,2])...>>>x,y=Foo()>>>x1>>>y2 最佳答案 是的。定义#to_ary。这将使您的对象被视为要分配的数组。irb>o=Obje

  7. Ruby 在 n *milli* 秒后超时一段代码 - 2

    在Ruby中,我需要在n毫秒秒后暂停一段代码的执行。我知道RubyTimeout库支持秒的超时:http://ruby-doc.org/stdlib/libdoc/timeout/rdoc/index.html这可能吗? 最佳答案 只需为超时使用十进制值。n毫秒的示例:Timeout::timeout(n/1000.0){sleep(100)} 关于Ruby在n*milli*秒后超时一段代码,我们在StackOverflow上找到一个类似的问题: https:

  8. ruby - 了解在 Ruby 中与 lambda 一起使用的 inject 行为 - 2

    我经常将预配置的lambda插入可枚举的方法中,例如“map”、“select”等。但是“注入(inject)”的行为似乎有所不同。例如与mult4=lambda{|item|item*4}然后(5..10).map&mult4给我[20,24,28,32,36,40]但是,如果我制作一个2参数lambda用于像这样的注入(inject),multL=lambda{|product,n|product*n}我想说(5..10).inject(2)&multL因为“inject”有一个可选的单个初始值参数,但这给了我......irb(main):027:0>(5..10).inject

  9. ruby-on-rails - 什么会导致与 APNS 的连接间歇性断开连接? - 2

    我有一个ruby​​脚本可以打开与Apple推送服务器的连接并发送所有待处理的通知。我看不出任何原因,但当Apple断开我的脚本时,我遇到了管道损坏错误。我已经编写了我的脚本来适应这种情况,但我宁愿只是找出它发生的原因,这样我就可以在第一时间避免它。它不会始终根据特定通知断开连接。它不会以特定的字节传输大小断开连接。一切似乎都是零星的。您可以在单个连接上发送的数据传输或有效负载计数是否有某些限制?看到人们的解决方案始终保持一个连接打开,我认为这不是问题所在。我看到连接在3次通知后断开,我看到它在14次通知后断开。我从未见过它能超过14点。有没有人遇到过这种类型的问题?如何处理?

  10. ruby - 奇怪的 ruby​​ for 循环行为(为什么这样做有效) - 2

    defreverse(ary)result=[]forresult[0,0]inaryendresultendassert_equal["baz","bar","foo"],reverse(["foo","bar","baz"])这行得通,我想了解原因。有什么解释吗? 最佳答案 如果我使用each而不是for/in重写它,它看起来像这样:defreverse(ary)result=[]#forresult[0,0]inaryary.eachdo|item|result[0,0]=itemendresultendforainb基本上就

随机推荐