Skip to content

Latest commit

 

History

History

02_waitgroups

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

⏳ WaitGroups: Synchronizing Goroutines

📚 What is a WaitGroup?

A WaitGroup is a synchronization primitive provided by Go’s sync package, which allows you to wait for a collection of goroutines to finish executing. It is useful when you launch multiple goroutines and need to block the main function (or any other goroutine) until all of them have completed their tasks.

Key Features of WaitGroup:

  • Counter-based: A WaitGroup maintains a counter that represents the number of goroutines it is waiting for.
  • Blocking: It allows one goroutine to block until all the goroutines in the group have finished executing.
  • Thread-safe: You can safely use a WaitGroup across multiple goroutines.

🧠 How to Use WaitGroup

To use a WaitGroup, you follow these basic steps:

  1. Add the number of goroutines that you want to wait for using Add().
  2. Launch goroutines as usual, but make sure to call Done() within each goroutine when it finishes.
  3. Wait for the goroutines to complete using Wait().

Example 1: Basic Usage of WaitGroup

package main

import (
	"fmt"
	"sync"
)

func printMessage(message string, wg *sync.WaitGroup) {
	defer wg.Done()  // Decrement the counter when the goroutine finishes
	fmt.Println(message)
}

func main() {
	var wg sync.WaitGroup

	wg.Add(2) // We are going to wait for 2 goroutines

	go printMessage("Hello from goroutine 1!", &wg)
	go printMessage("Hello from goroutine 2!", &wg)

	wg.Wait()  // Block until the counter becomes 0
	fmt.Println("All goroutines finished!")
}

Explanation:

  • We use wg.Add(2) to indicate that we are waiting for two goroutines.
  • Each goroutine calls wg.Done() when it completes.
  • The main function blocks at wg.Wait() until both goroutines have finished.

⚙️ How it Works

  1. Add: Before starting the goroutines, you call Add(n) to set the number of goroutines you expect to wait for.
  2. Done: Each goroutine must call Done() when it finishes its task. This decreases the counter by 1.
  3. Wait: The Wait() function blocks the calling goroutine until the counter reaches zero, which means all goroutines have finished.

Important Notes:

  • Defer Done: It’s common practice to use defer wg.Done() in each goroutine to ensure that it is called when the goroutine completes, even if an error occurs.
  • Thread-safety: You can safely modify the WaitGroup counter across different goroutines, but you should always call Done() after the task completes.

🛠️ Common Use Cases

WaitGroups are commonly used in situations where:

  • You launch multiple goroutines to handle concurrent tasks and need to wait for all of them to finish.
  • You are running multiple parallel operations (e.g., web requests, file operations, or data processing) and want to ensure that all tasks complete before moving forward.

Best Practices with WaitGroup

  • Avoid race conditions: Make sure the counter is updated correctly in concurrent scenarios to avoid any issues.
  • Use Defer for Done(): Always defer wg.Done() to ensure it is called even if the goroutine exits unexpectedly (e.g., due to a panic).
  • Don’t call Add() while waiting: Avoid calling Add() after you’ve started waiting with Wait()—this can lead to race conditions.

🚀 Next Steps

After mastering WaitGroups, the next step is learning how to handle mutexes to manage data access between goroutines. You can also explore channels for inter-goroutine communication.