మాడ్యూల్ పాఠాలు (1/5)
గోరౌటీన్స్: తేలికైన సమాంతరత
ఒక గోరౌటిన్ అనేది గో ద్వారా నిర్వహించబడే ఏకకాలిక అమలు యొక్క యూనిట్
అమలు సమయం. మీరు ఫంక్షన్ ముందు go కీవర్డ్తో ఒకదాన్ని ప్రారంభించండి
కాల్:
go greet("Anna") // chiamata a funzione esistente
go func() { // funzione anonima
fmt.Println("hi")
}()go స్టేట్మెంట్ వెంటనే తిరిగి వస్తుంది: గోరౌటిన్ ప్రారంభమవుతుంది
సమాంతరంగా మరియు కాలర్ కొనసాగుతుంది.
అవి ఎందుకు "తేలికైనవి"
- ప్రారంభ స్టాక్ ~2KB (అవసరమైతే వందల MB వరకు డైనమిక్గా పెరుగుతుంది).
- రన్టైమ్ (
GOMAXPROCS) ద్వారా తక్కువ సంఖ్యలో OS థ్రెడ్లపై మల్టీప్లెక్స్ చేయబడింది. - వేల/మిలియన్ల గోరౌటీన్లు నిత్యకృత్యం; OS థ్రెడ్లతో అవి అసాధ్యం.
సంభావితంగా ఇది "ఏకకాలిక అగ్ని-మరియు-మర్చి", కానీ అన్నిటితో
సమన్వయం చేయడానికి ఇడియోమాటిక్ సాధనాలు (ఛానెల్లు, sync.WaitGroup,
context).
ప్రధాన వేచి లేదు
func main() {
go func() { fmt.Println("ciao dalla goroutine") }()
// main esce subito: niente garanzia che la goroutine completi
}main తిరిగి వచ్చినప్పుడు, ప్రాసెస్ ముగుస్తుంది: గోరౌటీన్లు పొందలేరు
"వారి పనిని పూర్తి చేయడానికి", వారు కేవలం వారితో కలిసి చంపబడతారు
ప్రక్రియ. స్పష్టమైన సమకాలీకరణ అవసరం.
సమకాలీకరణ: ఒక ప్రివ్యూ
మీరు తదుపరి పాఠాలలో చూసే మూడు సాధనాలు:
// 1) Channel: la goroutine "segnala" via canale
done := make(chan struct{})
go func() {
work()
done <- struct{}{}
}()
<-done // attendi
// 2) sync.WaitGroup: N goroutine
var wg sync.WaitGroup
wg.Add(1)
go func() { defer wg.Done(); work() }()
wg.Wait()
// 3) context: cancellazione/timeout propagati"క్లాసిక్" క్లోజర్-ఇన్-లూప్ బగ్
గో 1.21 వరకు ఇది తరచుగా గోచా:
for i := 0; i < 3; i++ {
go func() { fmt.Println(i) }() // stampa "3 3 3" su versioni vecchie
}Go 1.22 నుండి for వేరియబుల్ ప్రతిదానిపై తాజాగా సృష్టించబడింది
పునరావృతం, కాబట్టి బగ్ డిఫాల్ట్గా పరిష్కరించబడుతుంది. పాత కోడ్బేస్లలో మీరు చేస్తారు
ఇప్పటికీ పరిష్కార నమూనాను చూడండి:
for i := 0; i < 3; i++ {
i := i // shadow esplicito
go func() { fmt.Println(i) }()
}
// oppure passa come argomento:
for i := 0; i < 3; i++ {
go func(n int) { fmt.Println(n) }(i)
}గోరూటిన్ != OS థ్రెడ్
| కోణం | గోరూటిన్ | OS థ్రెడ్ |
|---|---|---|
| ప్రారంభ స్టాక్ | ~2 KB | 1–8 MB (ప్రారంభంలో కేటాయించబడింది) |
| సృష్టి | నానోసెకన్లు | మైక్రోసెకన్లు |
| షెడ్యూలింగ్ | గో రన్టైమ్ (సహకార) | కెర్నల్ (ముందస్తు) |
| ప్రాక్టికల్ కౌంట్ | 100K+ | కొన్ని వేల |
ఒకే OS థ్రెడ్ అనేక గోరౌటిన్లను హోస్ట్ చేయగలదు. రన్టైమ్ కదులుతుంది అవసరమైనప్పుడు థ్రెడ్ల అంతటా గోరూటీన్లు.
దీనిని ప్రయత్నించండి
గ్రీట్ ఫంక్షన్ను గోరూటీన్గా ప్రారంభించి, సమయంతో పాటు 100మి.లు వేచి ఉండండి. మెయిన్ నుండి నిష్క్రమించే ముందు నిద్రపోండి.
సూచనను చూపించు
ఫంక్షన్ కాల్ ముందు `గో` గోరౌటిన్ని లాంచ్ చేస్తుంది.
3 ప్రయత్నాల తర్వాత పరిష్కారం లభిస్తుంది
'హాయ్' అని ప్రింట్ చేసే గోరౌటిన్గా అనామక ఫంక్షన్ను ప్రారంభించండి.
సూచనను చూపించు
అనామక ఫంక్షన్ `()`: `go func(){...}()` ట్రైలింగ్తో పిలువబడుతుంది.
3 ప్రయత్నాల తర్వాత పరిష్కారం లభిస్తుంది
గోరౌటిన్ పూర్తయ్యేలోపు `మెయిన్` నిష్క్రమిస్తే ఏమి జరుగుతుంది?
func main() {
go work()
// main ritorna immediatamente
}రీక్యాప్
go f()f()ని ఏకకాలంలో లాంచ్ చేస్తుంది; అది వెంటనే తిరిగి వస్తుంది.- గోరౌటిన్ = ~2 KB ప్రారంభ, కొన్ని OS థ్రెడ్లలో మల్టీప్లెక్స్ చేయబడింది.
mainవేచి ఉండదు: మీకు సమకాలీకరణ అవసరం (ఛానల్/వెయిట్గ్రూప్/సందర్భం).time.Sleepఅనేది ఉపదేశానికి సంబంధించినది, ఉత్పత్తిలో సమకాలీకరణ కోసం ఎప్పుడూ ఉండదు.- గో 1.22 నుండి
forవేరియబుల్ ప్రతి పునరావృతంలో "ఫ్రెష్"గా ఉంటుంది (ఇక "3 3 3" బగ్ లేదు).