1

As mentioned in golang doc, sync is intent for low level library routines.

Other than the Once and WaitGroup types, most are intended for use by low-level library routines. Higher-level synchronization is better done via channels and communication.

I am not quite understanding this statement and I use sync like the example below.
My purpose is just to let main thread wait until all the other threads finish, similar to .join() in c++ thread library.

Questions:
1: Is that proper to use sync like this? Or should I use channel instead of sync?
2: What is the difference between channel and sync?

var wg sync.WaitGroup      // declare the variable globally

func send(a string, b string){
    defer wg.Done()
    // do something
}
func main(){
    for i:=0; i<50; i++ {
         wg.Add(1)              // add delta
         go send("1111", "2222")
    }
    wg.Wait()                  // wait until wg becomes 0
}

Any suggestions are appreciate! Thanks!

rayimpr
  • 95
  • 1
  • 14
  • 1
    I'm not sure what you're asking, you your `send` goroutine has a different `sync.WaitGroup` than the one in `main()`, so there's no synchronization going on. – JimB Dec 06 '16 at 20:36
  • @JimB hey, sorry for the vague statement! I have updated. Actually I use sync here to do something like `.join()` in c++ thread. From the doc, channel can also do in this way. Is that proper to use sync? – rayimpr Dec 06 '16 at 21:05
  • 1
    Yes, that's what WaitGroup is for; waiting on a group of goroutines. I don't understand the question of "proper way to use sync", since that is an entire package, and you use what it provides it when you need it. This _isn't_ the proper way to use a `sync.WaitGroup`, since the `wg` value in `main` is different than the `wg` value in `send`. – JimB Dec 06 '16 at 21:08
  • @JimB Thanks for pointing out the problem of the title, I have updated! For `wg`, I declare it as a global variable. I guess all the new thread executing `send()` should have the same `wg` like `main()`? Also, if it is not the proper way to use `sync.WaitGroup`, what should I do to with the example? Thanks a lot! – rayimpr Dec 06 '16 at 21:18
  • Your problem was solely the different `wg` values. This is exactly how it's shown in the [`sync.WaitGroup` docs](https://golang.org/pkg/sync/#example_WaitGroup). – JimB Dec 06 '16 at 21:26
  • @JimB Thanks! Now I declare the `wg` as a global variable. I guess it works. – rayimpr Dec 06 '16 at 21:37
  • Conventional practice is to pass a `*sync.WaitGroup` as a parameter to the goroutine. The package-level variable is adequate in this specific example. – Charlie Tumahai Dec 06 '16 at 23:40
  • @MellowMarmot Got it! Thx – rayimpr Dec 07 '16 at 00:00
  • Possible duplicate of [Example for sync.WaitGroup correct?](http://stackoverflow.com/questions/19208725/example-for-sync-waitgroup-correct) – John S Perayil Dec 07 '16 at 05:18

2 Answers2

2

This example could help you

var wg sync.WaitGroup
done := make(chan bool)

for _, element := range slice {
    wg.Add(1)
    go func(elem interface{}) {
        wg.Done()
    }(element)
}

go func() {
    wg.Wait()
    done <- true
}()

for {
    select {
    case done:
        fmt.Println("All goroutines completed")
        close(done)
        return
    case time.After(time.Minute * 2):
        fmt.Println("Timeout!")
        return
    }
}
mylk
  • 21
  • 1
  • 5
-1

I don't know whether it is proper, but code below does the trick without using lower level 'sync'.

package main

func send(a string, b string, c chan bool) {
//  println( a, b )
    c <- true;
}

func
main() {

    c := make( chan bool )

    for i:=0; i<50; i++ {
        go send("1111", "2222", c)
    }

    w := 0
    for _ = range c {
        w += 1
        if w == 50 { break }
    }

}
Satachito
  • 5,838
  • 36
  • 43
  • The usage of range over channel is not appropriate, AFAIK. What if any of the routines has not been send to the channel yet - the loop will not run. – Krishna Gupta Aug 08 '20 at 14:24