Go में समवर्तीता और मल्टीथ्रेडिंग: उन्नत स्तर
Go (Golang) को शुरू से ही स्केलेबल और उच्च-प्रदर्शन वाले अनुप्रयोग लिखने के लिए डिज़ाइन किया गया था। इसके मूल में गोरूटीन और चैनल पर आधारित एक शक्तिशाली समवर्तीता मॉडल है। यदि आपने पहले ही go func() और सरल चैनलों के साथ बुनियादी उदाहरणों में महारत हासिल कर ली है, तो अब अगले स्तर पर जाने का समय आ गया है। इस लेख में, हम Go में समवर्तीता के साथ काम करने के उन्नत पैटर्न पर चर्चा करेंगे, जो आपको विश्वसनीय, कुशल और सुरक्षित कोड लिखने में मदद करेंगे।
1. गोरूटीन के जीवनचक्र का प्रबंधन: Context और WaitGroup
सबसे आम समस्याओं में से एक गोरूटीन लीक है। एक गोरूटीन जो चैनल से डेटा की अनंत प्रतीक्षा करती है, कभी समाप्त नहीं होगी यदि चैनल गलत तरीके से बंद किया गया हो। Go में गोरूटीन के जीवनचक्र को प्रबंधित करने के लिए दो मुख्य उपकरण हैं: sync.WaitGroup और context.Context।
समाप्ति की प्रतीक्षा के लिए sync.WaitGroup
sync.WaitGroup का उपयोग करें जब आपको गोरूटीन के एक निश्चित सेट के पूरा होने की प्रतीक्षा करनी हो। यह एक सरल और कुशल तंत्र है।
package main
import (\t"fmt"\t"sync"\t"time")
func worker(id int, wg *sync.WaitGroup) {\tdefer wg.Done() // बाहर निकलने पर काउंटर घटाएं\tfmt.Printf("Worker %d ने काम शुरू किया", id)\ttime.Sleep(time.Second)\tfmt.Printf("Worker %d ने काम खत्म किया", id)}
func main() {\tvar wg sync.WaitGroup
\tfor i := 1; i <= 3; i++ {\t\twg.Add(1) // शुरू करने से पहले काउंटर बढ़ाएं\t\tgo worker(i, &wg)\t}
\twg.Wait() // तब तक ब्लॉक करें जब तक काउंटर 0 न हो जाए\tfmt.Println("सभी वर्कर समाप्त हो गए")}रद्दीकरण और समय सीमा के लिए context.Context
जब कोई गोरूटीन लूप में काम कर रही हो या लंबा ऑपरेशन कर रही हो, तो उसे बाहरी संकेत पर सही ढंग से समाप्त होने में सक्षम होना चाहिए। context.Context रद्दीकरण, समय सीमा या टाइमआउट का संकेत देने का मानक तरीका है।
package main
import (\t"context"\t"fmt"\t"time")
func longRunningTask(ctx context.Context) {\tfor {\t\tselect {\t\tcase <-ctx.Done():\t\t\tfmt.Println("गोरूटीन को रुकने का संकेत मिला")\t\t\treturn\t\tdefault:\t\t\ttime.Sleep(500 * time.Millisecond)\t\t\tfmt.Println("काम कर रहा हूँ...")\t\t}\t}}
func main() {\tctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)\tdefer cancel() // संसाधनों को मुक्त करने के लिए cancel को कॉल करना महत्वपूर्ण है
\tgo longRunningTask(ctx)
\ttime.Sleep(3 * time.Second)\tfmt.Println("Main समाप्त हुआ")}2. चैनल: बफरिंग, बंद करना और Fan-Out/Fan-In पैटर्न
चैनल गोरूटीन के बीच सिंक्रनाइज़ेशन और डेटा स्थानांतरण का प्राथमिक तरीका है। उन्नत स्तर पर, बफर वाले और बिना बफर वाले चैनलों के बीच अंतर को समझना, उन्हें सही ढंग से बंद करना और एकत्रीकरण पैटर्न का उपयोग करना महत्वपूर्ण है।
बफर वाले बनाम बिना बफर वाले
बिना बफर वाला चैनल (बिना बफर) प्रेषक को तब तक ब्लॉक करता है जब तक प्राप्तकर्ता डेटा नहीं पढ़ लेता। बफर वाला चैनल बफर भरने तक बिना प्रतीक्षा किए कई संदेश भेजने की अनुमति देता है। चुनाव कार्य पर निर्भर करता है: सख्त सिंक्रनाइज़ेशन के लिए बिना बफर वाले का उपयोग करें, लोड को सुचारू करने के लिए बफर वाले का उपयोग करें।
Fan-Out/Fan-In पैटर्न
यह सबसे शक्तिशाली पैटर्न में से एक है। Fan-Out - कार्यों को कई गोरूटीन (वर्कर) में वितरित करना। Fan-In - कई गोरूटीन से परिणामों को एक चैनल में एकत्र करना।
package main
import (\t"fmt"\t"sync")
func producer(nums ...int) <-chan int {\tout := make(chan int)\tgo func() {\t\tfor _, n := range nums {\t\t\tout <- n\t\t}\t\tclose(out)\t}()\treturn out}
func square(in <-chan int) <-chan int {\tout := make(chan int)\tgo func() {\t\tfor n := range in {\t\t\tout <- n * n\t\t}\t\tclose(out)\t}()\treturn out}
func merge(channels ...<-chan int) <-chan int {\t