How to Use the sync.WaitGroup for Goroutine Synchronization in Go

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Installation and Setup
  4. Using sync.WaitGroup for Goroutine Synchronization
  5. Example: Parallel Image Processing
  6. Conclusion


Introduction

In Go, goroutines allow us to execute concurrent operations efficiently. However, sometimes we need to ensure that all goroutines have completed before proceeding with the next steps of our program. That’s where the sync.WaitGroup comes in. It provides a simple mechanism to synchronize goroutines and wait for them to finish.

In this tutorial, we will learn how to use the sync.WaitGroup in Go to synchronize goroutines and wait for their completion. By the end of this tutorial, you will be able to leverage this powerful feature to handle concurrent operations effectively.

Prerequisites

To follow along with this tutorial, you should have a basic understanding of Go programming language syntax and fundamentals. You should also have Go installed on your machine.

Installation and Setup

Before we begin, let’s ensure that Go is installed and set up properly on your machine. You can check if Go is installed by running the following command in your terminal:

go version

If Go is not installed, you can download and install it from the official Go website: https://golang.org/dl/

Using sync.WaitGroup for Goroutine Synchronization

The sync package in Go provides a WaitGroup type that allows us to wait for a collection of goroutines to finish executing. It provides three key methods: Add(), Done(), and Wait().

The Add() method is used to add the number of goroutines we want to wait for. We typically call Add() before spawning the goroutines.

The Done() method is called by each goroutine when it completes its execution. It decrements the internal counter of the WaitGroup.

The Wait() method blocks until the internal counter becomes zero. It effectively waits for all the goroutines to call Done().

Let’s now dive into an example to see how to use the sync.WaitGroup to synchronize goroutines.

Example: Parallel Image Processing

Suppose we have a list of images that we want to process concurrently. We can start a goroutine for each image, process them independently, and then wait for all the goroutines to finish before proceeding to the next step.

Here’s an example of parallel image processing using the sync.WaitGroup:

package main

import (
	"fmt"
	"sync"
	"time"
)

func processImage(image string, wg *sync.WaitGroup) {
	defer wg.Done()

	// Simulate processing time
	time.Sleep(1 * time.Second)

	fmt.Println("Processed image:", image)
}

func main() {
	images := []string{"image1.jpg", "image2.jpg", "image3.jpg"}

	var wg sync.WaitGroup
	wg.Add(len(images))

	for _, image := range images {
		go processImage(image, &wg)
	}

	wg.Wait()

	fmt.Println("All images processed.")
}

In this example, we define a processImage function that takes an image filename and a pointer to a sync.WaitGroup. Inside the function, we simulate the image processing by sleeping for 1 second. Then, we call wg.Done() to indicate that this goroutine has finished processing.

In the main function, we create a sync.WaitGroup and add the number of images to it using wg.Add(len(images)). This sets the internal counter of the WaitGroup to the number of goroutines we expect to wait for.

Next, we iterate over the images slice and spawn a goroutine for each image, passing the image filename and a pointer to the WaitGroup to the processImage function.

After spawning all the goroutines, we call wg.Wait() to block the execution until the internal counter becomes zero, i.e., until all the goroutines have called wg.Done().

Finally, we print a message indicating that all the images have been processed.

Let’s run this program and see the output:

Processed image: image1.jpg
Processed image: image3.jpg
Processed image: image2.jpg
All images processed.

As you can see, the images are processed concurrently, and the final message is only printed after all goroutines have completed.

Conclusion

In this tutorial, we learned how to use the sync.WaitGroup in Go to synchronize goroutines and wait for their completion. We explored the methods provided by the WaitGroup type: Add(), Done(), and Wait(). We then implemented a parallel image processing example to demonstrate the usage of sync.WaitGroup.

By leveraging the sync.WaitGroup, we can ensure our goroutines are synchronized and wait for them to complete before proceeding with the rest of our program. This allows for efficient and concurrent execution of tasks in Go.

Now that you understand the basics of sync.WaitGroup, you can apply this knowledge to scenarios where synchronization between goroutines is required.

Happy coding!