【问题标题】:Use go routine to initialize multiple services使用 goroutine 初始化多个服务
【发布时间】:2020-02-03 17:21:05
【问题描述】:

试图让自己熟悉子例程和整体 Go,我正在尝试编写一个脚本,该脚本基本上将使用 sync.WaitGroup 启动我的 django 应用程序的所有服务并保持它们运行,直到我手动终止 Go 脚本,这就是为什么我没有 intitialize() 函数实际上告诉等待组进程已完成。收到可怕的fatal error: all goroutines are asleep - deadlock! 消息。

 func main() {
    var wg sync.WaitGroup
    os.Chdir("/home/Projects/djangoapp")
    cc := []cmds{cmds{
        name:  "django",
        cmdsl: []string{"/home/Projects/djangoapp/env/bin/python", "manage.py", "runserver"},
    },
        cmds{
            name:  "celeryd",
            cmdsl: []string{"/home/Projects/djangoapp/env/bin/celery", "-A", "djangoapp", "worker", "-l", "INFO", "-S", "django"},
        },
    }

    for x := 0; x < 2; x++ {
        wg.Add(1)
        fmt.Println("starting up", cc[x].name)
        go initialize(cc[x])
    }
    wg.Wait()
}

func initialize(ccmds cmds) {
    cmd := exec.Command(ccmds.cmdsl[0], ccmds.cmdsl[1:]...)
    cmd.Env = append(os.Environ(), "DJANGO_SETTINGS_MODULE=articleadmin.settings.default")

    fmt.Println("initializing", ccmds.name)
    cmd.Start()
    fmt.Println("started", ccmds.name)
    cmd.Wait()
}

它启动服务,但随后出现死锁错误。我做错了什么?

【问题讨论】:

  • 这可能是因为你从来没有打电话给wg.Done。您应该将 WaitGroup 作为指针 (&amp;wg) 传递给您的初始化函数,然后在完成后调用 wg.Done()

标签: go subroutine


【解决方案1】:

goroutine 完成后您似乎忘记调用 wg.Done

 go initialize(&wg,cc[x])
...

func initialize(wg *sync.WaitGroup,ccmds cmds) {
  defer wg.Done()
  ...
}

否则,wg.Wait 将无限期等待。当所有的 goroutine 都终止时,main goroutine 将是唯一等待该 WaitGroup 的 goroutine,所以死锁。

【讨论】:

  • 就是这样。我希望它无限期地等待,直到我杀死脚本。 goroutines 应该无限期地继续运行。
  • 如果你遇到死锁错误,你的 goroutines 就结束了。你会遇到死锁,因为 wg.Wait 正在等待并且没有其他 goroutine 在运行。
  • “我希望它无限期地等待,直到我杀死脚本”那为什么还要使用等待组呢?
  • 我不需要使用等待组,很高兴使用任何最有效的方法。
  • 您的问题不在于使用等待组。你希望你的 goroutines 永远不会结束,但他们显然会这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-15
  • 2018-02-22
  • 1970-01-01
  • 1970-01-01
  • 2011-07-08
  • 2023-03-05
  • 2013-04-23
相关资源
最近更新 更多