sync.WaitGroup का उपयोग
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
// 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")
}
Login to try C/C++/Java/PHP code in the editor
Add Before, Done Inside
Add(1) को हर goroutine के लिए इसे launch करने से ठीक पहले एक बार main goroutine से call किया जाना चाहिए -- इसे नए goroutine के अंदर से call करना Wait() के Add चलने से पहले ही return होने का जोखिम रखता है।
उदाहरण: Add Before, Done Inside
// 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")
}
Login to try C/C++/Java/PHP code in the editor
Passing WaitGroup by Pointer
किसी sync.WaitGroup को पहले उपयोग के बाद कभी copy नहीं करना चाहिए -- इसे हमेशा एक pointer (*sync.WaitGroup) के रूप में पास करें, क्योंकि इसे copy करना code के अलग हिस्सों को स्वतंत्र, असंगत counters देगा।
उदाहरण: Passing WaitGroup by Pointer
// 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)
}
Login to try C/C++/Java/PHP code in the editor
- wg.Add() को goroutine launch करने से पहले के बजाय इसके अंदर call करना, counter की initial value पर एक race बनाते हुए।
- हर goroutine के अंदर wg.Done() call करना (अक्सर defer के ज़रिए) भूल जाना, जिससे Wait() हमेशा के लिए block हो जाता है।
- किसी 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: