go - 等待所有go例程,非阻塞

标签 go

我有一个关于 Go 例程的问题。

我的代码:

func main() {

    ok := make(chan bool, 1)

    i := 0
    fmt.Println("Starting...")
    for i <= 3 {
        fmt.Println("Loop: ", i)
        go long(ok, i)
        time.Sleep(1 * time.Second)
        i = i + 1

        select {
        case _ = <-ok:
        default:
            fmt.Println("Default")
        }
    }

    fmt.Println("Done...")

}

func long(c chan bool, i int){
    fmt.Println("Inside long: ", i)
    time.Sleep(3 * time.Second)
    fmt.Println("Done with loop: ", i)
    c <- true

}

这给了我输出:

Starting...
Loop:  0
Inside long:  0
Default
Loop:  1
Inside long:  1
Default
Loop:  2
Inside long:  2
Done with loop:  0
Loop:  3
Inside long:  3
Done with loop:  1
Done...

因为我在select中使用了default,所以 channel 是非阻塞的。主函数退出,所有当前例程也退出。然后我阅读了有关 syncWaitGrops 的内容。

func main() {

    ok := make(chan bool, 1)

    var wg sync.WaitGroup

    i := 0
    fmt.Println("Starting...")
    for i <= 3 {
        fmt.Println("Loop: ", i)
        wg.Add(1)
        go long(ok, i)
        time.Sleep(1 * time.Second)
        i = i + 1

        select {
            case _ = <-ok:
            default:
                fmt.Println("Default")
        }
    }

    wg.Wait()
    fmt.Println("Done...")

}

这给了我:

Starting...
Loop:  0
Inside long:  0
Default
Loop:  1
Inside long:  1
Default
Loop:  2
Inside long:  2
Done with loop:  0
Loop:  3
Inside long:  3
Done with loop:  1
Done with loop:  2
Done with loop:  3

我们现在更接近我想要的执行,即: for 循环使其对函数的所有调用都进行,然后我得到异步结果。如果一切顺利的话那就太好了。但会产生错误:

fatal error: all goroutines are asleep - deadlock! 

这是为什么?我应该如何解决它? (是否可以在不知道 wg.Add() 执行多少次的情况下修复?)

最佳答案

您需要在 WaitGroup 上调用 Done() 次数与调用 Add(1) 次数相同,以便 wg .Wait()可以解除阻塞。您不再需要 channel 来同步:

package main

import (
  "sync"
  "fmt"
  "time"
)

func main() {
    var wg sync.WaitGroup

    i := 0
    fmt.Println("Starting...")
    for i <= 3 {
        fmt.Println("Loop: ", i)
        wg.Add(1)
        go long(&wg, i)
        time.Sleep(1 * time.Second)
        i = i + 1
    }
    wg.Wait()
    fmt.Println("Done...")
}

func long(wg *sync.WaitGroup, i int){
    fmt.Println("Inside long: ", i)
    time.Sleep(3 * time.Second)
    fmt.Println("Done with loop: ", i)
    wg.Done()
}

关于go - 等待所有go例程,非阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50052851/

相关文章:

google-app-engine - Martini oauth2callback适配GAE后重定向到oauth2error

go - 自创建以来,Go 发生了很大变化吗?

oop - 确保嵌入式结构实现接口(interface)而不引入歧义

templates - 如何使用结构或变量值的字段作为模板名称?

csv - 处理上传的 csv 文件

go - 单值上下文中的多值无返回函数

Go:使用 TCP 连接写入 header

unit-testing - 优步 Cadence : How do I assert the call to workflow. sleep ()?

c++ - 在 Go (golang) 和 C++ 之间交换数据结构(数组)

go - 为什么这个缓冲的 channel 在我的代码中没有阻塞?