WaitGroups & Mutex in Go

List Topics
February 18, 2025
No Comments
5 min read

In Go, WaitGroups and Mutex are two important synchronization mechanisms used to coordinate the execution of concurrent goroutines. They help in managing the flow of goroutines, ensuring that tasks are completed or data access is controlled appropriately.

1️⃣ WaitGroups

A WaitGroup is used to wait for a collection of goroutines to finish executing. It allows one or more goroutines to wait for others to complete before continuing with the program.

Key Functions:

  • Add(n int): Increments the counter by n. Typically, you would call this before starting any goroutines to indicate how many goroutines to wait for.
  • Done(): Decrements the counter by 1. Each goroutine should call this once it finishes its work.
  • Wait(): Blocks until the counter is zero, meaning all goroutines have completed.

Example:

Go
package main

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

func main() {
    var wg sync.WaitGroup

    // Adding 2 goroutines to the WaitGroup
    wg.Add(2)

    // First goroutine
    go func() {
        defer wg.Done() // Decrement the counter when done
        time.Sleep(2 * time.Second)
        fmt.Println("Goroutine 1 finished")
    }()

    // Second goroutine
    go func() {
        defer wg.Done() // Decrement the counter when done
        time.Sleep(1 * time.Second)
        fmt.Println("Goroutine 2 finished")
    }()

    // Wait for all goroutines to finish
    wg.Wait()
    fmt.Println("All goroutines finished")
}

🔹 Output:

Bash
Goroutine 2 finished
Goroutine 1 finished
All goroutines finished

👉 In this example, wg.Wait() ensures that the program waits for both goroutines to finish before printing "All goroutines finished."

2️⃣ Mutex (Mutual Exclusion)

A Mutex is used to ensure that only one goroutine can access a particular section of code at a time, preventing data races. It provides mutual exclusion when accessing shared resources.

Key Functions:

  • Lock(): Acquires the lock. If another goroutine already holds the lock, the calling goroutine will block until the lock is available.
  • Unlock(): Releases the lock. This allows other goroutines to acquire the lock and continue their work.

Example:

Go
package main

import (
    "fmt"
    "sync"
)

var (
    counter int
    mu      sync.Mutex
)

func increment() {
    mu.Lock()        // Lock the mutex before accessing the shared resource
    counter++
    mu.Unlock()      // Unlock the mutex after updating the counter
}

func main() {
    var wg sync.WaitGroup

    // Add 5 goroutines to the WaitGroup
    wg.Add(5)

    // Start 5 goroutines that increment the counter
    for i := 0; i < 5; i++ {
        go func() {
            defer wg.Done() // Decrement the counter when done
            increment()
        }()
    }

    // Wait for all goroutines to finish
    wg.Wait()

    fmt.Println("Counter value:", counter)
}

🔹 Output:

Bash
Counter value: 5

👉 In this example, a Mutex is used to prevent multiple goroutines from simultaneously accessing and modifying the counter variable, ensuring the result is accurate.

3️⃣ Using WaitGroups and Mutex Together

You can combine WaitGroups and Mutex to coordinate goroutines while also ensuring that shared resources are accessed safely.

Example:

Go
package main

import (
    "fmt"
    "sync"
)

var (
    counter int
    mu      sync.Mutex
)

func increment(wg *sync.WaitGroup) {
    mu.Lock()
    counter++
    mu.Unlock()
    wg.Done()
}

func main() {
    var wg sync.WaitGroup

    // Add 5 goroutines to the WaitGroup
    wg.Add(5)

    // Start 5 goroutines that increment the counter
    for i := 0; i < 5; i++ {
        go increment(&wg)
    }

    // Wait for all goroutines to finish
    wg.Wait()

    fmt.Println("Final Counter value:", counter)
}

🔹 Output:

Bash
Final Counter value: 5

👉 In this case, the WaitGroup ensures that the main function waits for all goroutines to finish, and the Mutex ensures that the counter is safely incremented by one goroutine at a time.

Summary:

  • WaitGroups allow synchronization between goroutines, ensuring that the main goroutine waits for other goroutines to finish their execution.
  • Mutexes prevent data races by allowing only one goroutine to access shared resources at a time.
  • By combining both, you can manage concurrency and protect shared data effectively.

WaitGroups & Mutex in Go

Go-তে WaitGroups এবং Mutex দুটি গুরুত্বপূর্ণ সিঙ্ক্রোনাইজেশন মেকানিজম যা concurent goroutines-এর এক্সিকিউশন নিয়ন্ত্রণ করতে ব্যবহৃত হয়। এগুলি goroutines-এর প্রবাহ পরিচালনা করতে এবং ডেটা অ্যাক্সেস নিয়ন্ত্রণ করতে সাহায্য করে।

1️⃣ WaitGroups

একটি WaitGroup ব্যবহার করা হয় একাধিক goroutines-এর কাজ শেষ হওয়া পর্যন্ত অপেক্ষা করতে। এটি একটি বা একাধিক goroutine-এর কাজ শেষ হওয়া পর্যন্ত প্রোগ্রাম চলমান রাখে।

প্রধান ফাংশনসমূহ:

  • Add(n int): কাউন্টারকে n পরিমাণে বৃদ্ধি করে। সাধারণত, আপনি goroutine শুরু করার আগে এটি কল করেন যাতে আপনি জানাতে পারেন যে কতগুলি goroutine শেষ হওয়ার জন্য অপেক্ষা করতে হবে।
  • Done(): কাউন্টার ১ কমিয়ে দেয়। প্রতিটি goroutine যখন তার কাজ শেষ করে তখন এটি কল করা উচিত।
  • Wait(): যতক্ষণ না কাউন্টার শূন্য হয়, অর্থাৎ সমস্ত goroutine শেষ হয়, ততক্ষণ এটি ব্লক থাকে।

উদাহরণ:

Go
package main

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

func main() {
    var wg sync.WaitGroup

    // WaitGroup-এ 2 goroutine যোগ করা
    wg.Add(2)

    // প্রথম goroutine
    go func() {
        defer wg.Done() // কাজ শেষ হলে কাউন্টার কমানোর জন্য
        time.Sleep(2 * time.Second)
        fmt.Println("Goroutine 1 finished")
    }()

    // দ্বিতীয় goroutine
    go func() {
        defer wg.Done() // কাজ শেষ হলে কাউন্টার কমানোর জন্য
        time.Sleep(1 * time.Second)
        fmt.Println("Goroutine 2 finished")
    }()

    // সব goroutine শেষ হওয়া পর্যন্ত অপেক্ষা করা
    wg.Wait()
    fmt.Println("All goroutines finished")
}

🔹 Output:

Bash
Goroutine 2 finished
Goroutine 1 finished
All goroutines finished

👉 এখানে, wg.Wait() নিশ্চিত করে যে প্রোগ্রামটি "All goroutines finished" মুদ্রণ করার আগে দুটি goroutine-এর কাজ শেষ হওয়া পর্যন্ত অপেক্ষা করে।

2️⃣ Mutex (Mutual Exclusion)

একটি Mutex ব্যবহৃত হয়, যাতে কেবলমাত্র এক goroutine এক সময়ে একটি নির্দিষ্ট কোড সেকশনে প্রবেশ করতে পারে, যা ডেটা রেস প্রতিরোধ করে। এটি শেয়ার করা রিসোর্সগুলির অ্যাক্সেস নিয়ন্ত্রণ করতে সাহায্য করে।

প্রধান ফাংশনসমূহ:

  • Lock(): লক গ্রহণ করে। যদি অন্য কোনো goroutine ইতোমধ্যে লকটি ধারণ করে থাকে, তবে এই goroutine অপেক্ষা করবে যতক্ষণ না লকটি পাওয়া যায়।
  • Unlock(): লকটি মুক্ত করে। এটি অন্য goroutines-কে লকটি অর্জন করতে এবং তাদের কাজ চালিয়ে যেতে সাহায্য করে।

উদাহরণ:

Go
package main

import (
    "fmt"
    "sync"
)

var (
    counter int
    mu      sync.Mutex
)

func increment() {
    mu.Lock()        // শেয়ার করা রিসোর্সে অ্যাক্সেস করতে লক নেয়া
    counter++
    mu.Unlock()      // কাজ শেষ হলে লক মুক্ত করা
}

func main() {
    var wg sync.WaitGroup

    // 5 goroutine যোগ করা হচ্ছে WaitGroup-এ
    wg.Add(5)

    // 5 goroutine শুরু করা হচ্ছে, যেগুলি কাউন্টার বাড়াবে
    for i := 0; i < 5; i++ {
        go func() {
            defer wg.Done() // কাজ শেষ হলে কাউন্টার কমানোর জন্য
            increment()
        }()
    }

    // সব goroutine শেষ হওয়া পর্যন্ত অপেক্ষা করা
    wg.Wait()

    fmt.Println("Counter value:", counter)
}

🔹 Output:

Bash
Counter value: 5

👉 এখানে, Mutex নিশ্চিত করে যে একসাথে একাধিক goroutine কাউন্টার পরিবর্তন করতে পারবে না, যা ডেটা রেস প্রতিরোধ করে এবং সঠিক ফলাফল নিশ্চিত করে।

3️⃣ WaitGroups এবং Mutex একসাথে ব্যবহার

আপনি WaitGroups এবং Mutex একসাথে ব্যবহার করতে পারেন গোরুটিনগুলো সিঙ্ক্রোনাইজ করতে এবং শেয়ার করা রিসোর্স নিরাপদভাবে অ্যাক্সেস করতে।

উদাহরণ:

Go
package main

import (
    "fmt"
    "sync"
)

var (
    counter int
    mu      sync.Mutex
)

func increment(wg *sync.WaitGroup) {
    mu.Lock()
    counter++
    mu.Unlock()
    wg.Done()
}

func main() {
    var wg sync.WaitGroup

    // WaitGroup-এ 5 goroutine যোগ করা হচ্ছে
    wg.Add(5)

    // 5 goroutine শুরু করা হচ্ছে, যেগুলি কাউন্টার বাড়াবে
    for i := 0; i < 5; i++ {
        go increment(&wg)
    }

    // সব goroutine শেষ হওয়া পর্যন্ত অপেক্ষা করা
    wg.Wait()

    fmt.Println("Final Counter value:", counter)
}

🔹 Output:

Bash
Final Counter value: 5

👉 এখানে, WaitGroup নিশ্চিত করে যে প্রধান ফাংশনটি সমস্ত goroutines শেষ হওয়া পর্যন্ত অপেক্ষা করবে, এবং Mutex নিশ্চিত করে যে একই সময়ে একাধিক goroutine কাউন্টার পরিবর্তন করবে না।

সারসংক্ষেপ:

  • WaitGroups goroutines-এর মধ্যে সিঙ্ক্রোনাইজেশন তৈরি করতে ব্যবহৃত হয়, যাতে প্রধান goroutine অন্যান্য goroutine-এর কাজ শেষ হওয়া পর্যন্ত অপেক্ষা করে।
  • Mutexes ডেটা রেস প্রতিরোধ করে এবং শেয়ার করা রিসোর্সে একযোগে একাধিক goroutine অ্যাক্সেস করতে পারে না নিশ্চিত করে।
  • উভয়ই একসাথে ব্যবহার করা যেতে পারে, যেখানে goroutines-এর কাজ সিঙ্ক্রোনাইজ করা এবং শেয়ার করা ডেটা নিরাপদভাবে অ্যাক্সেস নিশ্চিত করা হয়।

©2025 Linux Bangla | Developed & Maintaind by Linux Bangla.