ప్రధాన కంటెంట్‌కు వెళ్లండి
మాడ్యూల్ 7 · 5లో పాఠం 4కోర్సులో 34/50~14 min
మాడ్యూల్ పాఠాలు (4/5)

`sync.Mutex` మరియు `sync.WaitGroup`

ఛానెల్‌లు గో యొక్క ప్రాథమిక ఇడియమ్, కానీ కొన్నిసార్లు మరింత సాంప్రదాయంగా ఉంటాయి ఆదిమానవులు కావాలి. sync ప్యాకేజీ మ్యూటెక్స్‌లను అందిస్తుంది, వేచి ఉండండి భాగస్వామ్య స్థితిని సమన్వయం చేయడానికి సమూహాలు మరియు ఇతర వినియోగాలు.

sync.Mutex: ప్రత్యేకమైన లాక్

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 గోరౌటిన్‌ల కోసం వేచి ఉండండి

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. కౌంటర్ 0కి తిరిగి వెళ్లే వరకు wg.Wait() బ్లాక్‌లు.

sync.Once: థ్రెడ్-సేఫ్ లేజీ ఇనిషియలైజేషన్

Go
var (
    once   sync.Once
    config *Config
)

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

once.Doలోని కాల్‌బ్యాక్ ఏకకాలంలో కూడా సరిగ్గా ఒకసారి నడుస్తుంది కాల్స్. సింగిల్టన్ / సోమరితనం ప్రారంభ నమూనా.

Mutex vs ఛానెల్: ఎప్పుడు ఏమి ఉపయోగించాలి

మార్గదర్శకాలు (అధికారిక Go FAQ నుండి కూడా):

కేసుఇష్టపడే సాధనం
డేటా యాజమాన్యాన్ని దాటుతోందిఛానెల్
పనిని పంపిణీ చేస్తోంది (పని క్యూ)ఛానెల్
స్వతంత్ర గోరౌటిన్‌లను సమన్వయం చేయడంఛానెల్
struct ఫీల్డ్‌ను రక్షించడంమ్యూటెక్స్
కాష్ / కౌంటర్మ్యూటెక్స్ లేదా పరమాణు
సింగిల్టన్ సూచనsync.Once

"ఆర్కెస్ట్రేట్ చేయడానికి ఛానెల్‌లు, షేర్డ్ డేటా కోసం మ్యూటెక్స్" అనేది మంచి నియమం.

రేస్ డిటెక్టర్

డేటా రేసులను గుర్తించడానికి -raceతో పరీక్షలను అమలు చేయండి:

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

రేస్ డిటెక్టర్ బైనరీని సాధన చేస్తుంది మరియు సమకాలీకరించని ప్రతిదాన్ని లాగ్ చేస్తుంది షేర్డ్ మెమరీకి యాక్సెస్. ఇది ఏకకాల కోడ్‌ని ధృవీకరించడానికి సాధనం #1 ఉత్పత్తికి ముందు.

దీనిని ప్రయత్నించండి

వ్యాయామం#go.m7.l4.e1
ప్రయత్నాలు: 0లోడ్ అవుతోంది...

mu.Lock() + defer 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: Add ముందు go, Doneతో defer, Wait వేచి ఉండండి.
  • sync.Once: థ్రెడ్-సేఫ్ లేజీ ఇనిషియలైజేషన్.
  • "ఆర్కెస్ట్రేట్ చేయడానికి ఛానెల్‌లు, షేర్డ్ డేటా కోసం మ్యూటెక్స్".
  • go test -race: డేటా రేసులను గుర్తించడానికి సాధనం #1.