In concurrent programming, it's crucial to control how many goroutines execute simultaneously. One approach is to use a buffered channel as a semaphore. However, a common issue arises when waiting for the semaphore to drain completely.
Let's say we have a slice of integers that we want to process concurrently, with a limit of two concurrent go routines. We use a buffered channel as a semaphore to enforce this limit. While the code works for most integers, the program exits prematurely before the last go routines finish due to the buffer never reaching emptiness.
How do we wait for the buffered channel to drain completely, ensuring all go routines complete before the program exits?
Using a channel to wait for a specific condition is not feasible due to the lack of a race-free way to check its length. Instead, we can employ a sync.WaitGroup to monitor the completion of all goroutines.
sem := make(chan struct{}, 2) var wg sync.WaitGroup for _, i := range ints { wg.Add(1) // acquire semaphore sem <- struct{}{} // start long running go routine go func(id int) { defer wg.Done() // do something // release semaphore <-sem }(i) } wg.Wait()
By using sync.WaitGroup, we can wait for all goroutines to finish before the program exits, ensuring that all processing is complete.
The above is the detailed content of How to Ensure All Goroutines Complete When Using a Buffered Channel as a Semaphore?. For more information, please follow other related articles on the PHP Chinese website!