sync.Mutex का उपयोग
In this page:
var mu sync.Mutex
mu.Lock()
defer mu.Unlock()
// critical section
Protecting Shared State
एक sync.Mutex यह सुनिश्चित करता है कि एक समय में सिर्फ एक goroutine Lock() और Unlock() के बीच का code execute कर सके, concurrent goroutines को एक साथ इसे modify करके shared data corrupt करने से रोकते हुए।
उदाहरण: Protecting Shared State
// Every Go file belongs to a package; main builds an executable
package main
// Import the packages this program uses
import (
"fmt"
"sync"
)
// Define a struct type named Counter
type Counter struct {
mu sync.Mutex
value int
}
// Define the method Increment on type Counter
func (c *Counter) Increment() {
c.mu.Lock()
// defer runs this call when the surrounding function returns
defer c.mu.Unlock()
c.value++
}
// main is where the program starts running
func main() {
// Short declaration: create c and infer the type
c := &Counter{}
// Declare wg with the zero value of its type
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
c.Increment()
}()
}
wg.Wait()
fmt.Println(c.value)
}
Login to try C/C++/Java/PHP code in the editor
Always Pair Lock with defer Unlock
Lock() के तुरंत बाद defer उपयोग करना गारंटी देता है कि function चाहे कैसे भी exit हो -- जल्दी returns या एक panic सहित -- Unlock() चलेगा, जो permanently हर दूसरे goroutine को lock out करने से बचाता है।
उदाहरण: Always Pair Lock with defer Unlock
// Every Go file belongs to a package; main builds an executable
package main
// Import the packages this program uses
import (
"fmt"
"sync"
)
// Define a struct type named SafeMap
type SafeMap struct {
mu sync.Mutex
data map[string]int
}
// Define the method Set on type SafeMap
func (m *SafeMap) Set(key string, value int) {
m.mu.Lock()
// defer runs this call when the surrounding function returns
defer m.mu.Unlock()
m.data[key] = value
}
// main is where the program starts running
func main() {
// Short declaration: create m and infer the type
m := &SafeMap{data: make(map[string]int)}
m.Set("a", 1)
// Print the values followed by a newline
fmt.Println(m.data)
}
Login to try C/C++/Java/PHP code in the editor
What Happens Without a Mutex
बिना किसी mutex (या दूसरे synchronization) के, एक ही variable को concurrently पढ़ने और लिखने वाले कई goroutines एक data race produce करते हैं -- एक अप्रत्याशित, कभी-कभी चुपचाप गलत result जो हर run में अलग हो सकता है।
उदाहरण: What Happens Without a Mutex
// 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 mu with the zero value of its type
var mu sync.Mutex
// Short declaration: create total and infer the type
total := 0
// Declare wg with the zero value of its type
var wg sync.WaitGroup
// Loop: repeat while the condition holds
for i := 0; i < 50; i++ {
wg.Add(1)
// Start this call in a new goroutine (runs concurrently)
go func() {
defer wg.Done()
mu.Lock()
total++
mu.Unlock()
}()
}
wg.Wait()
fmt.Println("total:", total)
}
Login to try C/C++/Java/PHP code in the editor
- Lock() के बाद Unlock() call करना भूल जाना, permanently उस mutex का इंतज़ार कर रहे हर दूसरे goroutine को block करते हुए।
- एक mutex lock करना, फिर बिना unlock किए किसी error path पर जल्दी return करना -- हमेशा Lock() को एक deferred Unlock() के साथ जोड़ें।
- sync.Mutex रखने वाले किसी struct को value से copy करना, जो lock को दोहराता है और mutual exclusion की गारंटी तोड़ देता है।
- sync.Mutex mutual exclusion प्रदान करता है: एक समय में सिर्फ एक goroutine lock रख सकता है।
- Lock() mutex acquire करता है (अगर दूसरा goroutine इसे रखे हो तो block करते हुए), Unlock() इसे release करता है।
- Lock() के ठीक बाद defer mu.Unlock() release की गारंटी देने का standard तरीका है, जल्दी returns पर भी।
- एक mutex shared data को concurrent, unsynchronized access से बचाता है जो अन्यथा एक data race का कारण बनता।
Chapter Quiz — Complete all 8 topics to unlock
0/8 topics done
Complete these topics first: