• about reply
Alpha Reply Logo
Menu
  • Solutions
    Solutions
    • Solutions
    • Fusion
    • Synapse
  • Insights
    Insights
    • Insights
    • Success Stories
    • Articles
    • Events
    • Tutorials
  • Partnerships
Choose language:
  • about Reply
Alpha Reply Logo
Focus On

Go Concurrency with WaitGroup

goconcurrencywithwaitgroup-1408x704.jpg 0

Welcome back to the series tutorials on Go Concurrency. If you missed the previous tutorials please refer to: Go Concurrency with GoRoutines.

In this tutorial, we will help you to understand the concept of WaitGroup.

What is WaitGroup

In some scenarios, you may need to block certain parts of code to allow these GoRoutines to complete their execution according to your needs. A common usage of WaitGroup is to block the main function because we know that the main function itself is also a GoRoutine.

package main
 
import (
    "fmt"
    "sync"
)
 
func main() {
 
    wg := sync.WaitGroup{}
    wg.Add(1)
 
    go print(&wg)
 
    wg.Wait()
 
    fmt.Println("hello from main")
}
 
func print(wg *sync.WaitGroup) {
    fmt.Println("hello from goroutine")
    wg.Done()
}

You need to import the sync package before you can use WaitGroup. WaitGroup is of struct type and it has three functions, which you can use: Add(int), Wait() and Done(). The mechanics of the WaitGroup is that it has a counter that starts at zero. Whenever you call Add(int), you are increasing the counter by the parameter specified in the Add(int) function.

On the other hand, each Done() function decreases the counter by 1. The WaitGroup panics if the counter is less than 0 and therefore, you need to make sure Done() is not called more than you need to. Moreover, if you use Done() before Add(), it will also cause a panic. The Wait() function blocks the code and it will be released until the counter is zero.

In the example, we first declare a variable wg and instantiate a new sync.WaitGroup{}. We call Add(1) before attempting to execute our go print(). We then pass the pointer to wg in print() so that we can use Done() function once the print task is completed. We call wg.Wait() to block the main GoRoutine and it will release the block until the go print() is done.

Can you spot the problem?

A little exercise for the reader, the following code produces deadlock. Do you know why?

package main
import (
    "fmt"
    "sync"
)
 
func main() {
 
    wg := sync.WaitGroup{}
    wg.Add(2)
 
    go printCat(&wg)
    wg.Wait()
 
    go printDog(&wg)
    wg.Wait()
 
    fmt.Println("hello from main")
}
 
func printCat(wg *sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        fmt.Println("Cat")
    }
    wg.Done()
}
 
func printDog(wg *sync.WaitGroup){
    for i := 0; i < 5; i++ {
        fmt.Println("Dog")
    }
    wg.Done()
}
 

This is because the main GoRoutine has been blocked forever by the first wg.Wait(). We increase the counter of wg by 2 by using wg.Add(2). After the printCat() GoRoutine finishes, the counter remains 1 and blocks the main GoRoutine forever.

Multiple GoRoutines with WaitGroup

Let's have a look at another example to illustrate the power of using GoRoutines to multithread for loop in Go if each iteration is independent to one another.

package main

import (
   "fmt"
   "sync"
)

func main() {

   wg := sync.WaitGroup{}
   for i:=0; i<10; i++{
      wg.Add(1)
      go dosomething(&wg)

   }

   wg.Wait()
   fmt.Println("Finish for loop")
}

func dosomething(wg *sync.WaitGroup) {
   fmt.Println("Do something")
   wg.Done()
}

We spawn one GoRoutine at each iteration of the for loop and each GoRoutine will perform a task which is independent to the other tasks. The benefit of using GoRoutines here is that the next iteration does not need to wait for the previous task to finish. We are using WaitGroups to finish the execution of all tasks within the for loop before we execute fmt.Println("Finish for loop").

So far, all GoRoutines have no communication between them. In the next tutorial, we will introduce the concept of Channels which make data sharing between GoRoutines possible.

Stay tuned!

RELATED CONTENTS

Go concurrency with Mutex 0

Go concurrency with Mutex

Mutex is one of the most critical concepts in concurrent programming. When you use GoRoutine and Channels to perform concurrent programming, have you ever thought about what happens when two GoRoutines try to access the same piece of data in the same memory location? ...

Go Concurrency with Channels

In this tutorial, we will help you understand the concept of Channels. With concurrency programming, communication in a memory sharing environment plays a vital role in synchronisation across your programme. In Go, Channels area built-in feature for synchronisation purposes. They mainly act as...

Go Concurrency with Channels 0

go concurrency with goroutines

Golang has become a popular language due to the features that allow developers to build incredibly fast applications using the power of concurrency programming. In this series of tutorials, we will learn about...

go concurrency with goroutines 0
 
 
 
 
Reply ©​​ 2023​ - Company Information -
 PrivacyCookie Settings​​
  • About Reply​
  • Inves​tors​​
  • Newsroom
  • Follow us on
  • ​​
​​
  • ​
  • ​Privacy & Cookies Policy​
  • Information (Client)
  • Information (Supplier)
  • Information (Candidate)​​