मॉड्यूल पाठ (4/5)
`sync.Mutex` और `sync.WaitGroup`
चैनल गो का प्राथमिक मुहावरा है, लेकिन कभी-कभी अधिक पारंपरिक होता है
आदिम की जरूरत है. sync पैकेज म्यूटेक्स प्रदान करता है, प्रतीक्षा करें
साझा स्थिति को समन्वित करने के लिए समूह और अन्य उपयोगिताएँ।
सिंक.म्यूटेक्स: एक्सक्लूसिव लॉक
import "sync"
type Counter struct {
mu sync.Mutex
count int
}
func (c *Counter) Inc() {
c.mu.Lock()
defer c.mu.Unlock()
c.count++
}
func (c *Counter) Get() int {
c.mu.Lock()
defer c.mu.Unlock()
return c.count
}एक समय में केवल एक गोरोइन Lock() और Unlock() के बीच प्रवेश करता है।
अनिवार्य पैटर्न: defer mu.Unlock() Lock() के ठीक बाद।
Sync.RWMutex: कई पाठक, एक लेखक
पढ़ने-भारी स्थिति के लिए:
var mu sync.RWMutex
mu.RLock() // read lock: più goroutine simultanee OK
v := data
mu.RUnlock()
mu.Lock() // write lock: esclusivo
data = newValue
mu.Unlock()केवल तभी उपयोगी है जब पढ़ा गया वास्तव में लिखने पर हावी हो; अन्यथा एक नियमित
sync.Mutex कम आंतरिकता के कारण सरल और अक्सर तेज़ है
विवाद.
sync.WaitGroup: N goroutines के लिए प्रतीक्षा करें
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
work(id)
}(i)
}
wg.Wait() // blocca finché tutti i Done() sono arrivatiकार्यप्रवाह:
wg.Add(N)काउंटर को N से बढ़ाता है (गोरोइन लॉन्च करने से पहले)।- प्रत्येक गोरोइन समाप्त होने पर
wg.Done()पर कॉल करता है (आदर्श रूप सेdeferके माध्यम से)। wg.Wait()तब तक ब्लॉक करता है जब तक काउंटर 0 पर वापस नहीं चला जाता।
सिंक.एक बार: थ्रेड-सुरक्षित आलसी आरंभीकरण
var (
once sync.Once
config *Config
)
func GetConfig() *Config {
once.Do(func() {
config = loadConfig()
})
return config
}once.Do में कॉलबैक बिल्कुल एक बार चलता है, समवर्ती के तहत भी
कॉल. सिंगलटन/आलसी आरंभीकरण पैटर्न।
म्यूटेक्स बनाम चैनल: कब क्या उपयोग करें
दिशानिर्देश (आधिकारिक गो एफएक्यू से भी):
| केस | पसंदीदा उपकरण |
|---|---|
| डेटा का स्वामित्व पारित करना | चैनल |
| कार्य बाँटना (कार्य कतार) | चैनल |
| स्वतंत्र गोरआउट्स का समन्वय | चैनल |
| एक संरचना क्षेत्र की सुरक्षा करना | म्यूटेक्स |
| कैश/काउंटर | म्यूटेक्स या परमाणु |
| सिंगलटन संदर्भ | sync.Once |
"ऑर्केस्ट्रेट के लिए चैनल, साझा डेटा के लिए म्यूटेक्स" एक अच्छा नियम है।
रेस डिटेक्टर
डेटा दौड़ का पता लगाने के लिए -race के साथ परीक्षण चलाएँ:
go test -race ./...
go run -race main.goरेस डिटेक्टर बाइनरी को यंत्रित करता है और प्रत्येक अनसिंक्रनाइज़्ड को लॉग करता है साझा स्मृति तक पहुंच. समवर्ती कोड को मान्य करने के लिए यह टूल #1 है उत्पादन से पहले.
इसे अजमाएं
Mu.Lock() + defer mu.Unlock() के साथ गिनती की वृद्धि को सुरक्षित रखें।
संकेत दिखाएँ
लॉक() के तुरंत बाद mu.Unlock() को स्थगित करें, घबराहट होने पर भी रिहाई की गारंटी देता है।
3 प्रयासों के बाद समाधान उपलब्ध है
3 गोरोइन लॉन्च करें और सिंक.वेटग्रुप (प्रत्येक गोरोइन में जोड़ें(3), हो गया(), प्रतीक्षा करें()) का उपयोग करके उन सभी की प्रतीक्षा करें।
संकेत दिखाएँ
गोरोइन लॉन्च करने से पहले जोड़ें; विलंब के साथ गोरौटाइन के अंदर किया गया।
3 प्रयासों के बाद समाधान उपलब्ध है
म्यूटेक्स रिलीज़ होने की गारंटी के लिए अनुशंसित पैटर्न क्या है?
mu.Lock()
// ?संक्षिप्त
sync.Mutexसाझा स्थिति की सुरक्षा करता है; हमेशाdefer mu.Unlock().- म्यूटेक्स की प्रतिलिपि बनाने से बचने के लिए पॉइंटर रिसीवर का उपयोग करें।
sync.RWMutexकई-पाठकों/एक-लेखक पैटर्न के लिए (केवल अगर यह मदद करता है)।sync.WaitGroup:goसे पहलेAdd,Doneके साथdefer,Waitप्रतीक्षा करें।sync.Once: थ्रेड-सुरक्षित आलसी आरंभीकरण।- "ऑर्केस्ट्रेट करने के लिए चैनल, साझा डेटा के लिए म्यूटेक्स"।
go test -race: डेटा रेस का पता लगाने के लिए टूल #1।