Skip to content

Instantly share code, notes, and snippets.

@montanaflynn
Last active October 26, 2023 13:35
Show Gist options
  • Save montanaflynn/56c2d0de37b7e078ab5c12bd27b4115c to your computer and use it in GitHub Desktop.
Save montanaflynn/56c2d0de37b7e078ab5c12bd27b4115c to your computer and use it in GitHub Desktop.
A simple example of bounded concurrency and wait groups in Golang
package main
import (
"fmt"
"sync"
"time"
)
func main() {
// a blocking channel to keep concurrency under control
semaphoreChan := make(chan struct{}, 2)
defer close(semaphoreChan)
// a wait group enables the main process a wait for goroutines to finish
wg := sync.WaitGroup{}
// a simple loop from 1 to 10
for i := 1; i <= 10; i++ {
// increment the wait group internal counter
wg.Add(1)
// block until the semaphore channel has room
semaphoreChan <- struct{}{}
// print what we're about to be doing (will keep the order)
fmt.Printf("About to run #%d in a goroutine\n", i)
// fire off a goroutine with the index in a closure since it will be modified
go func(i int) {
// pretend to do some synchronous work
time.Sleep(time.Second)
// tell the wait group that we be done
wg.Done()
// print an message containing the index (won't keep order)
fmt.Printf("About to exit #%d from a goroutine\n", i)
// clear a spot in the semaphore channel
<-semaphoreChan
}(i)
}
// wait for all the goroutines to be done
wg.Wait()
}
@zokica
Copy link

zokica commented Mar 16, 2020

Thanks a lot for this, I know you've addressed this but I'll repeat it. Blocking should be done before spawning goroutines. You're leaking memory this way by spawning as many goroutines as you possibly can and having them wait. I don't think there's a benefit to blocking inside the goroutine.

@montanaflynn
Copy link
Author

That's a good point, I'll update the example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment