← Back to Go Course | Chapter 11: Concurrency | Lesson 5 of 8

sync.WaitGroup का उपयोग

एक WaitGroup एक checklist जैसा है जो गिनता है कि कितने workers अभी भी busy हैं, और यह boss को उस count के zero तक गिरने तक आगे बढ़ने से पहले इंतज़ार करने देता है।
Syntax
go
var wg sync.WaitGroup
wg.Add(1)
go func() {
    defer wg.Done()
    // work
}()
wg.Wait()

Waiting for Goroutines to Finish

sync.WaitGroup main goroutine को तब तक इंतज़ार करने देता है जब तक दूसरे goroutines का एक group सभी खत्म न हो जाए, time.Sleep जैसे fragile approaches की जगह एक precise, deterministic signal से।

उदाहरण: Waiting for Goroutines to Finish

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the packages this program uses
import (
	"fmt"
	"sync"
)

// main is where the program starts running
func main() {
	// Declare wg with the zero value of its type
	var wg sync.WaitGroup
	// Loop: repeat while the condition holds
	for i := 1; i <= 3; i++ {
		wg.Add(1)
		// Start this call in a new goroutine (runs concurrently)
		go func(n int) {
			// defer runs this call when the surrounding function returns
			defer wg.Done()
			// Print the values followed by a newline
			fmt.Println("task", n, "complete")
		}(i)
	}
	wg.Wait()
	fmt.Println("all tasks finished")
}

Add Before, Done Inside

Add(1) को हर goroutine के लिए इसे launch करने से ठीक पहले एक बार main goroutine से call किया जाना चाहिए -- इसे नए goroutine के अंदर से call करना Wait() के Add चलने से पहले ही return होने का जोखिम रखता है।

Note: goroutine के अंदर बिल्कुल पहली line के रूप में हमेशा wg.Done() defer करें, ताकि goroutine के panic होने पर भी यह चले।

उदाहरण: Add Before, Done Inside

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the packages this program uses
import (
	"fmt"
	"sync"
)

// Define the function process
func process(id int, wg *sync.WaitGroup) {
	// defer runs this call when the surrounding function returns
	defer wg.Done()
	// Print the values followed by a newline
	fmt.Println("processing item", id)
}

// main is where the program starts running
func main() {
	// Declare wg with the zero value of its type
	var wg sync.WaitGroup
	// Loop: repeat while the condition holds
	for i := 1; i <= 3; i++ {
		wg.Add(1)
		go process(i, &wg)
	}
	wg.Wait()
	fmt.Println("done")
}

Passing WaitGroup by Pointer

किसी sync.WaitGroup को पहले उपयोग के बाद कभी copy नहीं करना चाहिए -- इसे हमेशा एक pointer (*sync.WaitGroup) के रूप में पास करें, क्योंकि इसे copy करना code के अलग हिस्सों को स्वतंत्र, असंगत counters देगा।

उदाहरण: Passing WaitGroup by Pointer

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the packages this program uses
import (
	"fmt"
	"sync"
)

// Define the function worker
func worker(wg *sync.WaitGroup, results *[]int, mu *sync.Mutex, n int) {
	// defer runs this call when the surrounding function returns
	defer wg.Done()
	mu.Lock()
	*results = append(*results, n*n)
	mu.Unlock()
}

// main is where the program starts running
func main() {
	// Declare wg with the zero value of its type
	var wg sync.WaitGroup
	// Declare mu with the zero value of its type
	var mu sync.Mutex
	// Short declaration: create results and infer the type
	results := []int{}
	for i := 1; i <= 4; i++ {
		wg.Add(1)
		go worker(&wg, &results, &mu, i)
	}
	wg.Wait()
	fmt.Println(results)
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
आम गलतियां
  1. wg.Add() को goroutine launch करने से पहले के बजाय इसके अंदर call करना, counter की initial value पर एक race बनाते हुए।
  2. हर goroutine के अंदर wg.Done() call करना (अक्सर defer के ज़रिए) भूल जाना, जिससे Wait() हमेशा के लिए block हो जाता है।
  3. किसी sync.WaitGroup को pointer पास करने के बजाय value से किसी function में copy करना, जो चुपचाप इसकी counting तोड़ देता है।
चैप्टर सारांश
  • sync.WaitGroup इंतज़ार करने के लिए बाकी goroutines की एक count track करता है।
  • Add(n) counter बढ़ाता है, Done() इसे घटाता है, और Wait() तब तक block करता है जब तक यह zero तक न पहुंचे।
  • race से बचने के लिए हर goroutine launch करने से पहले Add() call करें, इसके अंदर से नहीं।
  • हमेशा एक *sync.WaitGroup पास करें (या इसे reference से रखें) -- इसे copy करना count तोड़ देता है।
🔒

Chapter Quiz — Complete all 8 topics to unlock

0/8 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.