【问题标题】:Manage a background operation (create / kill)管理后台操作(创建/杀死)
【发布时间】:2020-05-23 16:25:22
【问题描述】:

我第一次在这里发帖,因为我在互联网上找不到干净的解决方案。

我的目标很简单,我需要创建一个后台操作(goroutine或进程或其他什么...),我可以正确杀死(不要留在后台)。

我尝试了很多方法,例如使用 chan 或 context。

但我始终找不到避免泄漏的正确方法。

这是一个例子:

package main

import (
    "log"
    "strconv"
    "runtime"
    "time"
    "math/rand"
)

func main() {
    log.Println("goroutines: " + strconv.Itoa(runtime.NumGoroutine()))
    func1()
    leak := ""
    if runtime.NumGoroutine() > 1 {
        leak = " there is one LEAK !!"
    }
    log.Println("goroutines: " + strconv.Itoa(runtime.NumGoroutine()) + leak)
}

func func1() {

    done := make(chan struct{})
    quit := make(chan struct{})

    go func() {

        log.Println("goroutines: " + strconv.Itoa(runtime.NumGoroutine()))

        select {
        case <-quit:
            log.Println("USEFUL ???")
            return
        default:
            func2()
            done<-struct{}{}
        }
    }()

    select {
    case <-time.After(4 * time.Second):
        quit<-struct{}{}
        log.Println("TIMEOUT")
    case <-done:
        log.Println("NO TIMEOUT")
    }
}

func func2() {
    log.Println("JOB START")

    rand.Seed(time.Now().UnixNano())
    val := rand.Intn(10)
    log.Println("JOB DURATION: " + strconv.Itoa(val))
    time.Sleep(time.Duration(val) * time.Second) // fake a long process with an unknown duration

    log.Println("JOB DONE")
}

在这个例子中,如果工作在 4 秒超时之前完成,一切都很好,goroutine 的最终数量将为 1,否则它将像我能找到的每个示例一样为 2。

但这只是一个例子,也许用 goroutines 不可能,甚至在 Go 中也不可能......

【问题讨论】:

  • 这能回答你的问题吗? Stop goroutine execution on timeout
  • 谢谢,我已经看过那个帖子了;他们说杀死一个 goroutine 是不可能的;很好,但这只是一个例子,我不关心 goroutines。就像我写的那样,我只想杀死 Go 中的后台操作,但我不知道该怎么做 :) 如果您有任何建议

标签: go concurrency kill


【解决方案1】:

你的问题在这里:

quit := make(chan struct{})

go func() {
    for {
        select {
        case <-quit:
            log.Println("USEFUL ???")
            return
        default:
            func2()
            quit<-struct{}{}
            return
        }
    }
}()

这个 goroutine 在一个无缓冲通道上向自己发送信号。这意味着当它到达quit&lt;-struct{}{} 时,该发送将永远阻塞,因为它正在等待自身 接收。不过,尚不完全清楚这是如何工作的。这里发生了一些奇怪的事情:

  • goroutine 通过通道向自己发送信号,这似乎是错误的 - 它不应该需要与自己通信
  • 通道和循环似乎没有必要; quit&lt;-struct{}{} 可以替换为log.Println("USEFUL ???") 并且可以删除整个for/select/channel业务
  • 函数返回select 的每个case 中,所以无论如何把它放在一个循环中是没有意义的 - 没有这种代码可以永远执行循环的第二次迭代

【讨论】:

  • 感谢您的回答;我已经编辑了我的示例。我会记住拆分通道以进出通信(这里我用“完成”和“退出”分开)。但是,即使我删除了循环,我也看不到如何达到我的目标;又名杀死后台操作(goroutine,进程或其他......)如果你有任何线索
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-22
  • 1970-01-01
  • 2015-04-02
相关资源
最近更新 更多