Last active
October 26, 2023 13:35
-
-
Save montanaflynn/56c2d0de37b7e078ab5c12bd27b4115c to your computer and use it in GitHub Desktop.
A simple example of bounded concurrency and wait groups in Golang
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
} |
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
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.