首页 > 解决方案 > 如何确保所有 goroutines 没有 time.Sleep 终止?

问题描述

我正在尝试使用有关谁首先收到消息的例程进行试验。然而,当主 goroutine 终止时,一些 goroutine 仍然挂起。我通过panic. 但是,如果我添加time.Sleep它们都会终止。我猜这是因为,当主要的 go 例程结束时,Go 运行时找不到时间来终止其他例程。

    package main

    import (
        "fmt"
        "time"
    )

    func main() {
        for i := 0; i < 1000000; i++ {
            algo()
        }

        // without this, some goroutines do not terminate
        // time.Sleep(time.Second)

        panic("")
    }

    func algo() {
        c := make(chan int)
        wait := make(chan bool)

        go racer(1, wait, c)
        go racer(2, wait, c)
        go racer(3, wait, c)
        go racer(4, wait, c)
        go racer(5, wait, c)

        // who gets it first
        c <- 5
        close(wait)
    }

    func racer(name int, wait chan bool, c chan int) {
        select {
        case <-wait:
        case v := <-c:
            fmt.Println(name, ":", v)
        }
    }

标签: goconcurrency

解决方案


这正是sync.WaitGroup它的用途。这是取自这篇博文的一个玩具示例:

package main

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

func main() {
    messages := make(chan int)
    var wg sync.WaitGroup

    // you can also add these one at 
    // a time if you need to 

    wg.Add(3)
    go func() {
        defer wg.Done()
        time.Sleep(time.Second * 3)
        messages <- 1
    }()
    go func() {
        defer wg.Done()
        time.Sleep(time.Second * 2)
        messages <- 2
    }() 
    go func() {
        defer wg.Done()
        time.Sleep(time.Second * 1)
        messages <- 3
    }()
    go func() {
        for i := range messages {
            fmt.Println(i)
        }
    }()

    wg.Wait()
}

推荐阅读