Is it safe to call WaitGroup.Add concurrently from multiple go routines?

2,809 views
Skip to first unread message

San

unread,
Jan 1, 2017, 3:53:45 PM1/1/17
to golang-nuts
I don't see any mention about the safety of using WaitGroup from multiple goroutines in godoc.
I stumble upon "new Add calls must happen after all previous Wait calls have returned."
but given the use case of WaitGroup and the function name I am not quite sure about it.

For example in the last exercise of go tour.
I use WaitGroup like this
If I naively interpret the doc I'll guess that I should not call Add during Wait at all.
I wonder if this actually safe or not?

kevin.g...@sendgrid.com

unread,
Jan 2, 2017, 12:22:59 AM1/2/17
to golang-nuts
You can safely call Add concurrently from multiple goroutines in some cases. In the case of your example, I think it correctly satisfies the conditions mentioned in the documentation:
 
Note that calls with a positive delta that occur when the counter is zero must happen before a Wait. Calls with a negative delta, or calls with a positive delta that start when the counter is greater than zero, may happen at any time.

1) You ensure that Add is called at least once before Wait
2) No decrement (Done) occurs until after a corresponding increment

Therefore there should be no possibility for Wait to return until all recursive tasks have completed.

By the way, your example makes use of rather heavy conditional nesting; Go style lends itself toward flatter conditionals, like so: https://play.golang.org/p/zUOcTD6Ovc

Dave Cheney

unread,
Jan 2, 2017, 2:00:43 AM1/2/17
to golang-nuts
The race detector can answer this question for you I think.

San

unread,
Jan 2, 2017, 2:23:12 AM1/2/17
to golang-nuts
Thank you
I reread the document and still not quite sure if the function is safe to be called concurrently.
So I try the race detector which is not outputting any report. (Mean safe I supposed.)
Finally, I look at the source code which I found sync/atomic usage for counter manipulation so I sure about it.
Thank you both for the confirmation.

I have another question regarding the usage of race detector.
I don't know how it works so I wonder if it gives deterministic output or not?
Do I need to try it multiple times in order to make sure?

Dave Cheney

unread,
Jan 2, 2017, 2:25:36 AM1/2/17
to golang-nuts
While it isn't necessary to alter GOMAXPROCS to detect a race (or it is possible to have a data race at GOMAXPROCS==1) increasing the number of goroutines that can run in parallel, sometimes to ludicrous levels can expose non determinism in your code.

This is the script I use to test my packages.

https://dave.cheney.net/2013/06/19/stress-test-your-go-packages

Vinay Pai

unread,
Jan 3, 2017, 12:59:21 PM1/3/17
to golang-nuts
It is safe to call wg.Add fron multiple goroutines. The only caveat is that wg.Wait must be synchronized with the first wg.Add (which it is in your case because you call wg.Add(1) in the same goroutine as wg.Wait()).

The go source code is very readable, and easily accessible from godoc.  Here's the implementation of Add()


The underlying implementation of wg.Add uses atomic.UInt64Add to increment values and semaphores to do block and release waiting goroutines
Reply all
Reply to author
Forward
0 new messages