मुख्य सामग्री पर जाएं
मॉड्यूल 7 · पाठ 4 का 5पाठ्यक्रम में 34/50~14 min
मॉड्यूल पाठ (4/5)

`sync.Mutex` और `sync.WaitGroup`

चैनल गो का प्राथमिक मुहावरा है, लेकिन कभी-कभी अधिक पारंपरिक होता है आदिम की जरूरत है. sync पैकेज म्यूटेक्स प्रदान करता है, प्रतीक्षा करें साझा स्थिति को समन्वित करने के लिए समूह और अन्य उपयोगिताएँ।

सिंक.म्यूटेक्स: एक्सक्लूसिव लॉक

Go
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: कई पाठक, एक लेखक

पढ़ने-भारी स्थिति के लिए:

Go
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 के लिए प्रतीक्षा करें

Go
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

कार्यप्रवाह:

  1. wg.Add(N) काउंटर को N से बढ़ाता है (गोरोइन लॉन्च करने से पहले)।
  2. प्रत्येक गोरोइन समाप्त होने पर wg.Done() पर कॉल करता है (आदर्श रूप से defer के माध्यम से)।
  3. wg.Wait() तब तक ब्लॉक करता है जब तक काउंटर 0 पर वापस नहीं चला जाता।

सिंक.एक बार: थ्रेड-सुरक्षित आलसी आरंभीकरण

Go
var (
    once   sync.Once
    config *Config
)

func GetConfig() *Config {
    once.Do(func() {
        config = loadConfig()
    })
    return config
}

once.Do में कॉलबैक बिल्कुल एक बार चलता है, समवर्ती के तहत भी कॉल. सिंगलटन/आलसी आरंभीकरण पैटर्न।

म्यूटेक्स बनाम चैनल: कब क्या उपयोग करें

दिशानिर्देश (आधिकारिक गो एफएक्यू से भी):

केसपसंदीदा उपकरण
डेटा का स्वामित्व पारित करनाचैनल
कार्य बाँटना (कार्य कतार)चैनल
स्वतंत्र गोरआउट्स का समन्वयचैनल
एक संरचना क्षेत्र की सुरक्षा करनाम्यूटेक्स
कैश/काउंटरम्यूटेक्स या परमाणु
सिंगलटन संदर्भsync.Once

"ऑर्केस्ट्रेट के लिए चैनल, साझा डेटा के लिए म्यूटेक्स" एक अच्छा नियम है।

रेस डिटेक्टर

डेटा दौड़ का पता लगाने के लिए -race के साथ परीक्षण चलाएँ:

Bash
go test -race ./...
go run -race main.go

रेस डिटेक्टर बाइनरी को यंत्रित करता है और प्रत्येक अनसिंक्रनाइज़्ड को लॉग करता है साझा स्मृति तक पहुंच. समवर्ती कोड को मान्य करने के लिए यह टूल #1 है उत्पादन से पहले.

इसे अजमाएं

व्यायाम#go.m7.l4.e1
प्रयास: 0लोड हो रहा है...

Mu.Lock() + defer mu.Unlock() के साथ गिनती की वृद्धि को सुरक्षित रखें।

संपादक लोड हो रहा है...
संकेत दिखाएँ

लॉक() के तुरंत बाद mu.Unlock() को स्थगित करें, घबराहट होने पर भी रिहाई की गारंटी देता है।

3 प्रयासों के बाद समाधान उपलब्ध है

व्यायाम#go.m7.l4.e2
प्रयास: 0लोड हो रहा है...

3 गोरोइन लॉन्च करें और सिंक.वेटग्रुप (प्रत्येक गोरोइन में जोड़ें(3), हो गया(), प्रतीक्षा करें()) का उपयोग करके उन सभी की प्रतीक्षा करें।

संपादक लोड हो रहा है...
संकेत दिखाएँ

गोरोइन लॉन्च करने से पहले जोड़ें; विलंब के साथ गोरौटाइन के अंदर किया गया।

3 प्रयासों के बाद समाधान उपलब्ध है

Quiz#go.m7.l4.e3
तैयार

म्यूटेक्स रिलीज़ होने की गारंटी के लिए अनुशंसित पैटर्न क्या है?

Go
mu.Lock()
// ?
उत्तर विकल्प

संक्षिप्त

  • sync.Mutex साझा स्थिति की सुरक्षा करता है; हमेशा defer mu.Unlock().
  • म्यूटेक्स की प्रतिलिपि बनाने से बचने के लिए पॉइंटर रिसीवर का उपयोग करें।
  • sync.RWMutex कई-पाठकों/एक-लेखक पैटर्न के लिए (केवल अगर यह मदद करता है)।
  • sync.WaitGroup: go से पहले Add, Done के साथ defer, Wait प्रतीक्षा करें।
  • sync.Once: थ्रेड-सुरक्षित आलसी आरंभीकरण।
  • "ऑर्केस्ट्रेट करने के लिए चैनल, साझा डेटा के लिए म्यूटेक्स"।
  • go test -race: डेटा रेस का पता लगाने के लिए टूल #1।