繁体   English   中英

Golang 频道缺少一些值

[英]Golang channel missing some values

我有以下代码

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    concurrent := 12
    ch := make(chan int)
    defer close(ch)
    for i := 1; i <= concurrent; i++ {
        go worker(i, ch)
    }
    for i := 1; i <= 21; i++ {
        ch <- i
    }
}

func worker(worker int, ch chan int) {
    for requestId := range ch {
        fmt.Printf("worker %d is requesting to %d...\n", worker, requestId)
        time.Sleep(time.Duration(rand.Intn(3)) * time.Second)
    }
}

main function 启动多个运行worker function 的 goroutine,然后将一些值放入通道中,这些值由 worker 打印。 我的问题是有时通道中的最后一个值甚至更多值不是由工作人员打印的。

worker 10 is requesting to 10...
worker 5 is requesting to 1...
worker 5 is requesting to 13...
worker 7 is requesting to 6...
worker 2 is requesting to 2...
worker 3 is requesting to 7...
worker 3 is requesting to 14...
worker 6 is requesting to 4...
worker 11 is requesting to 9...
worker 9 is requesting to 8...
worker 9 is requesting to 15...
worker 12 is requesting to 11...
worker 8 is requesting to 12...
worker 8 is requesting to 16...
worker 4 is requesting to 5...
worker 1 is requesting to 3...
worker 11 is requesting to 17...

我认为这是因为主要的 function 结束并在打印最后一个值之前“杀死”所有正在运行的 goroutine,因为最后总是打印所有值。

func main() {
    concurrent := 12
    ch := make(chan int)
    defer close(ch)
    for i := 1; i <= concurrent; i++ {
        go worker(i, ch)
    }
    for i := 1; i <= 21; i++ {
        ch <- i
    }
    time.Sleep(3 * time.Second)
}

我怎样才能在不使用睡眠的情况下解决这个问题,并且尽可能只使用频道?

因为主 goroutine 在最后一个导致整个程序退出的for循环之后立即退出,所以后台 goroutine 可能会或可能不会有机会运行,您必须提供一些同步方式来“等待”所有工作 goroutines结束。

使用sync.WaitGroup

   func main() {

    concurrent := 12
    ch := make(chan int)

    var wg sync.WaitGroup
    for i := 1; i <= concurrent; i++ {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            worker(i, ch)
        }(i) // You have to pass i as parameter
    }
    for i := 1; i <= 21; i++ {
        ch <- i
    }
    close(ch) // Close channel to tell all workers to stop

    wg.Wait() // Wait all workers to finish its work
   }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM