What is the Advantage of sync.WaitGroup over Channels?

后端 未结 6 724
旧巷少年郎
旧巷少年郎 2021-01-30 10:33

I\'m working on a concurrent Go library, and I stumbled upon two distinct patterns of synchronization between goroutines whose results are similar:

Waitgroup



        
6条回答
  •  粉色の甜心
    2021-01-30 10:53

    If you are particularly sticky about using only channels, then it needs to be done differently (if we use your example does, as @Not_a_Golfer points out, it'll produce incorrect results).

    One way is to make a channel of type int. In the worker process send a number each time it completes the job (this can be the unique job id too, if you want you can track this in the receiver).

    In the receiver main go routine (which will know the exact number of jobs submitted) - do a range loop over a channel, count on till the number of jobs submitted are not done, and break out of the loop when all jobs are completed. This is a good way if you want to track each of the jobs completion (and maybe do something if needed).

    Here's the code for your reference. Decrementing totalJobsLeft will be safe as it'll ever be done only in the range loop of the channel!

    //This is just an illustration of how to sync completion of multiple jobs using a channel
    //A better way many a times might be to use wait groups
    
    package main
    
    import (
        "fmt"
        "math/rand"
        "time"
    )
    
    func main() {
    
        comChannel := make(chan int)
        words := []string{"foo", "bar", "baz"}
    
        totalJobsLeft := len(words)
    
        //We know how many jobs are being sent
    
        for j, word := range words {
            jobId := j + 1
            go func(word string, jobId int) {
    
                fmt.Println("Job ID:", jobId, "Word:", word)
                //Do some work here, maybe call functions that you need
                //For emulating this - Sleep for a random time upto 5 seconds
                randInt := rand.Intn(5)
                //fmt.Println("Got random number", randInt)
                time.Sleep(time.Duration(randInt) * time.Second)
                comChannel <- jobId
            }(word, jobId)
        }
    
        for j := range comChannel {
            fmt.Println("Got job ID", j)
            totalJobsLeft--
            fmt.Println("Total jobs left", totalJobsLeft)
            if totalJobsLeft == 0 {
                break
            }
        }
        fmt.Println("Closing communication channel. All jobs completed!")
        close(comChannel)
    
    }
    

提交回复
热议问题