परिचय मैं प्रकार और उपयोग के मामलों तथा इसका उपयोग कब करना है, इस पर चर्चा करना चाहता हूँ। sync.Cond क्या है? sync.Cond गो प्रोग्रामिंग भाषा में, एक प्रकार है जिसे पैकेज में परिभाषित किया गया है जो एक कंडीशन वैरिएबल का प्रतिनिधित्व करता है। कंडीशन वैरिएबल सिंक्रोनाइज़ेशन प्राइमिटिव हैं जिनका उपयोग गोरूटीन को समन्वयित करने के लिए किया जाता है, ताकि उन्हें आगे बढ़ने से पहले एक विशिष्ट कंडीशन के सत्य होने की प्रतीक्षा करने की अनुमति मिल सके। sync.Cond sync प्रकार कंडीशन वैरिएबल बनाने और प्रबंधित करने का एक तरीका प्रदान करता है। इसके तीन मुख्य तरीके हैं: sync.Cond : यह विधि कॉलिंग गोरआउटिन को तब तक प्रतीक्षा करने के लिए बाध्य करती है जब तक कि कोई दूसरा गोरआउटिन कंडीशन वैरिएबल को सिग्नल न दे। जब गोरआउटिन कॉल करता है, तो यह संबंधित लॉक को रिलीज़ करता है और तब तक निष्पादन को निलंबित करता है जब तक कि कोई दूसरा गोरआउटिन उसी वैरिएबल पर या कॉल न कर दे। Wait() Wait() sync.Cond Signal() Broadcast() : यह विधि कंडीशन वैरिएबल पर प्रतीक्षा कर रहे एक गोरूटीन को जगाती है। यदि कई गोरूटीन प्रतीक्षा कर रहे हैं, तो उनमें से केवल एक को जगाया जाता है। कौन सा गोरूटीन जागृत होगा इसका चुनाव मनमाना है और इसकी गारंटी नहीं है। Signal() : यह विधि कंडीशन वेरिएबल के लिए प्रतीक्षा कर रहे सभी गोरूटीन को जगाती है। जब को कॉल किया जाता है, तो सभी प्रतीक्षा कर रहे गोरूटीन जाग जाते हैं और आगे बढ़ सकते हैं। Broadcast() Broadcast() ध्यान दें कि कंडीशन वेरिएबल तक पहुंच को सिंक्रनाइज़ करने के लिए एक संबद्ध की आवश्यकता होती है। sync.Cond sync.Mutex का उपयोग करके, आप विशिष्ट स्थितियों के आधार पर गोरूटीन के निष्पादन को समन्वित कर सकते हैं, जिससे गो में अधिक नियंत्रित और सिंक्रनाइज़ समवर्ती प्रोग्रामिंग की अनुमति मिलती है। sync.Cond सामान्य उपयोग के मामले उपयोग आम तौर पर उन परिदृश्यों में किया जाता है जहाँ गोरूटीन को विशिष्ट स्थितियों के आधार पर एक दूसरे के साथ समन्वय और संचार करने की आवश्यकता होती है। आइए के सामान्य उपयोग के मामलों पर विचार करें। sync.Cond sync.Cond गोरूटीन सिंक्रोनाइजेशन उपयोग कई गोरूटीन के निष्पादन को सिंक्रनाइज़ करने के लिए किया जा सकता है। उदाहरण के लिए, आपके पास कई गोरूटीन हो सकते हैं जिन्हें आगे बढ़ने से पहले किसी विशिष्ट शर्त के संतुष्ट होने का इंतज़ार करना होगा। प्रतीक्षारत गोरूटीन को कॉल कर सकते हैं, और सिग्नलिंग गोरूटीन या को कॉल कर सकते हैं ताकि शर्त पूरी होने पर प्रतीक्षारत गोरूटीन को जगाया जा सके। sync.Cond cond.Wait() cond.Signal() cond.Broadcast() package main import ( "fmt" "sync" "time" ) func main() { var wg sync.WaitGroup var mu sync.Mutex cond := sync.NewCond(&mu) wg.Add(2) go func() { fmt.Println("Goroutine 1 is started") defer wg.Done() cond.L.Lock() defer cond.L.Unlock() fmt.Println("Goroutine 1 is waiting for condition") cond.Wait() fmt.Println("Goroutine 1 met the condition") fmt.Println("Goroutine 1 is done") }() go func() { fmt.Println("Goroutine 2 is started") defer wg.Done() time.Sleep(5 * time.Second) // Simulating some work cond.L.Lock() defer cond.L.Unlock() fmt.Println("Goroutine 2 is signaling condition") cond.Signal() fmt.Println("Goroutine 2 completed signaling") fmt.Println("Goroutine 2 is done") }() wg.Wait() } इस उदाहरण में, हमारे पास दो गोरूटीन हैं। पहला गोरूटीन उपयोग करके किसी शर्त का इंतज़ार करता है, जबकि दूसरा गोरूटीन उपयोग करके शर्त का संकेत देता है। cond.Wait() cond.Signal() जब प्रोग्राम निष्पादित होता है, तो पहला गोरूटीन लॉक प्राप्त करता है और फिर को कॉल करता है। चूंकि शर्त अभी तक पूरी नहीं हुई है, इसलिए पहला गोरूटीन लॉक को रिलीज़ करता है और इसके निष्पादन को निलंबित कर देता है। cond.Wait() इस बीच, दूसरा गोरूटीन पाँच सेकंड के लिए सो जाता है, कुछ काम का अनुकरण करता है। यह लॉक प्राप्त करता है और फिर को कॉल करता है। यह प्रतीक्षारत गोरूटीन को जगाता है, जो फिर लॉक प्राप्त करता है और निष्पादित करता है। cond.Signal() का उपयोग यह सुनिश्चित करता है कि पहला गोरूटीन तब तक प्रतीक्षा करता है जब तक कि दूसरा गोरूटीन स्थिति का संकेत नहीं देता, जिससे दो गोरूटीनों के बीच समन्वय और समन्वय संभव हो जाता है। sync.Cond उत्पादक-उपभोक्ता समस्या हल करने में उपयोगी हो सकता है, एक क्लासिक सिंक्रोनाइज़ेशन समस्या जिसमें दो प्रकार की प्रक्रियाएँ, उत्पादक और उपभोक्ता शामिल हैं, जो एक सामान्य निश्चित आकार के बफर या कतार को साझा करते हैं। जब नया डेटा उपभोग के लिए उपलब्ध होता है, तो उत्पादक गोरूटीन उपभोक्ता गोरूटीन को सूचित करने के लिए या का उपयोग कर सकते हैं। sync.Cond उत्पादक-उपभोक्ता समस्या को cond.Signal() cond.Broadcast() package main import ( "fmt" "sync" "time" ) const MaxMessageChannelSize = 5 func main() { var wg sync.WaitGroup var mu sync.Mutex cond := sync.NewCond(&mu) messageChannel := NewMessageChannel(MaxMessageChannelSize) producer := NewProducer(cond, messageChannel) consumer := NewConsumer(cond, messageChannel) wg.Add(2) go func() { defer wg.Done() for i := range 10 { producer.Produce(fmt.Sprintf("Message %d", i)) } }() go func() { defer wg.Done() for range 10 { consumer.Consume() } }() wg.Wait() } type MessageChannel struct { maxBufferSize int buffer []string } func NewMessageChannel(size int) *MessageChannel { return &MessageChannel{ maxBufferSize: size, buffer: make([]string, 0, size), } } func (mc *MessageChannel) IsEmpty() bool { return len(mc.buffer) == 0 } func (mc *MessageChannel) IsFull() bool { return len(mc.buffer) == mc.maxBufferSize } func (mc *MessageChannel) Add(message string) { mc.buffer = append(mc.buffer, message) } func (mc *MessageChannel) Get() string { message := mc.buffer[0] mc.buffer = mc.buffer[1:] return message } type Producer struct { cond *sync.Cond messageChannel *MessageChannel } func NewProducer(cond *sync.Cond, messageChannel *MessageChannel) *Producer { return &Producer{ cond: cond, messageChannel: messageChannel, } } func (p *Producer) Produce(message string) { time.Sleep(500 * time.Millisecond) // Simulating some work p.cond.L.Lock() defer p.cond.L.Unlock() for p.messageChannel.IsFull() { fmt.Println("Producer is waiting because the message channel is full") p.cond.Wait() } p.messageChannel.Add(message) fmt.Println("Producer produced the message:", message) p.cond.Signal() } type Consumer struct { id int cond *sync.Cond messageChannel *MessageChannel } func NewConsumer(cond *sync.Cond, messageChannel *MessageChannel) *Consumer { return &Consumer{ cond: cond, messageChannel: messageChannel, } } func (c *Consumer) Consume() { time.Sleep(1 * time.Second) // Simulating some work c.cond.L.Lock() defer c.cond.L.Unlock() for c.messageChannel.IsEmpty() { fmt.Println("Consumer is waiting because the message channel is empty") c.cond.Wait() } message := c.messageChannel.Get() fmt.Println("Consumer consumed the message:", message) c.cond.Signal() } इस उदाहरण में, हमारे पास एक निर्माता गोरूटीन है जो संदेश बनाता है और उन्हें संदेश चैनल में जोड़ता है और एक उपभोक्ता गोरूटीन है जो संदेशों का उपभोग करता है। संदेश चैनल का अधिकतम आकार द्वारा परिभाषित किया गया है। MaxMessageChannelSize निर्माता गोरूटीन संदेश चैनल में संदेश जोड़ता है और नया डेटा उपलब्ध होने पर उपभोक्ता गोरूटीन को सूचित करने के लिए का उपयोग करता है। यदि संदेश चैनल भरा हुआ है, तो निर्माता गोरूटीन का उपयोग करके तब तक प्रतीक्षा करता है जब तक कि उपभोक्ता कुछ डेटा का उपभोग नहीं कर लेता और संदेश चैनल में स्थान खाली नहीं कर देता। cond.Signal() cond.Wait() इसी तरह, उपभोक्ता गोरूटीन संदेश चैनल से संदेशों का उपभोग करता है और संदेश चैनल में स्थान उपलब्ध होने पर निर्माता गोरूटीन को सूचित करने के लिए का उपयोग करता है। यदि यह खाली है, तो उपभोक्ता गोरूटीन का उपयोग करके तब तक प्रतीक्षा करता है जब तक कि निर्माता कुछ डेटा तैयार करके उसे संदेश चैनल में नहीं जोड़ देता। cond.Signal() cond.Wait() यहाँ, निर्माता और उपभोक्ता गोरूटीन के बीच समन्वय और तुल्यकालन की अनुमति देता है। यह सुनिश्चित करता है कि जब संदेश चैनल खाली हो तो उपभोक्ता प्रतीक्षा करे, और जब यह भर जाए तो निर्माता प्रतीक्षा करे, जिससे निर्माता-उपभोक्ता समस्या हल हो जाती है। sync.Cond संसाधन सिंक्रनाइज़ेशन मान लीजिए कि कई गोरूटीन को किसी साझा संसाधन तक विशेष पहुँच की आवश्यकता है। पहुँच को समन्वित करने के लिए उपयोग किया जा सकता है। उदाहरण के लिए, वर्कर गोरूटीन के एक पूल को तब तक प्रतीक्षा करनी पड़ सकती है जब तक कि संसाधन की एक निश्चित संख्या उपलब्ध न हो जाए, उसके बाद ही वे प्रसंस्करण शुरू कर सकते हैं। गोरूटीन का उपयोग करके कंडीशन वैरिएबल पर प्रतीक्षा कर सकते हैं, और या का उपयोग करके संसाधन जारी करने के बारे में सूचित कर सकते हैं। sync.Cond cond.Wait() cond.Signal() cond.Broadcast() package main import ( "fmt" "sync" "time" ) const MaxResources = 3 func main() { var wg sync.WaitGroup var mu sync.Mutex cond := sync.NewCond(&mu) resourceProvider := NewResourceProvider(cond, MaxResources) wg.Add(10) for i := range 10 { go func(workerID int) { defer wg.Done() worker := NewWorker(workerID, cond, resourceProvider) worker.Run() }(i) } wg.Wait() } type ResourceProvider struct { maxResources int availableResources int cond *sync.Cond } func NewResourceProvider(cond *sync.Cond, maxResources int) *ResourceProvider { return &ResourceProvider{ cond: cond, availableResources: maxResources, } } func (rp *ResourceProvider) AvailableResources() int { return rp.availableResources } func (rp *ResourceProvider) AcquireResoirce() { rp.availableResources-- } func (rp *ResourceProvider) ReleaseResource() { rp.availableResources++ } type Worker struct { id int cond *sync.Cond rp *ResourceProvider } func NewWorker(workerID int, cond *sync.Cond, rp *ResourceProvider) *Worker { return &Worker{ id: workerID, cond: cond, rp: rp, } } func (w *Worker) Run() { w.cond.L.Lock() for w.rp.AvailableResources() == 0 { fmt.Printf("Worker %d is waiting for resources\n", w.id) w.cond.Wait() } w.rp.AcquireResoirce() fmt.Printf("Worker %d acquired resource. Remaining resources: %d\n", w.id, w.rp.AvailableResources()) w.cond.L.Unlock() time.Sleep(1 * time.Second) // Simulating work w.cond.L.Lock() defer w.cond.L.Unlock() w.rp.ReleaseResource() fmt.Printf("Worker %d released resource. Remaining resources: %d\n", w.id, w.rp.AvailableResources()) w.cond.Signal() } इस उदाहरण में, हमारे पास कई वर्कर गोरूटीन हैं जिन्हें सीमित संसाधनों तक विशेष पहुँच की आवश्यकता है। वर्कर गोरूटीन अन्य वर्करों के साथ समन्वय करने के लिए का उपयोग करके संसाधन प्राप्त करते हैं और रिलीज़ करते हैं। यदि कोई संसाधन उपलब्ध नहीं है, तो वर्कर गोरूटीन प्रतीक्षा करते हैं जब तक कि अन्य गोरूटीन संसाधन रिलीज़ नहीं कर देते। cond.Signal() using cond.Wait() इस उदाहरण में, कार्यकर्ता गोरूटीन के बीच समन्वय और समन्वय की अनुमति देता है, यह सुनिश्चित करता है कि जब कोई संसाधन उपलब्ध न हो तो कार्यकर्ता गोरूटीन प्रतीक्षा करें, जिससे संसाधन पहुंच को प्रभावी ढंग से सिंक्रनाइज़ किया जा सके। sync.Cond घटना अधिसूचना उपयोग सिस्टम में विशिष्ट घटनाओं या परिवर्तनों के बारे में गोरूटीन को सूचित करने के लिए किया जा सकता है। उदाहरण के लिए, आप किसी विशिष्ट घटना के लिए प्रतीक्षारत गोरूटीन रख सकते हैं। जब घटना होती है, तो सिग्नलिंग गोरूटीन या का उपयोग करके प्रतीक्षारत गोरूटीन को जगा सकता है और उन्हें घटना को संभालने की अनुमति दे सकता है। sync.Cond cond.Signal() cond.Broadcast() package main import ( "fmt" "sync" "time" ) const maxWorkersCount = 10 func main() { var counter int32 var wg sync.WaitGroup var mu sync.Mutex cond := sync.NewCond(&mu) wg.Add(maxWorkersCount) for i := range maxWorkersCount { go func(workerID int) { defer wg.Done() fmt.Printf("Worker %d performing work\n", workerID) time.Sleep(1 * time.Second) // Simulate work cond.L.Lock() defer cond.L.Unlock() counter++ if counter == maxWorkersCount { fmt.Println("All workers have reached the barrier") cond.Broadcast() } else { fmt.Printf("Worker %d is waiting at the barrier\n", workerID) cond.Wait() } fmt.Printf("Worker %d passed the barrier\n", workerID) }(i) } wg.Wait() } यहाँ, हमारे पास कई वर्कर गोरूटीन हैं जो काम करते हैं और बैरियर पॉइंट पर सिंक्रोनाइज़ करते हैं। वर्कर गोरूटीन काउंटर को बढ़ाते हैं और फिर या तो बैरियर पर प्रतीक्षा करते हैं या बैरियर तक पहुँचने वाले वर्कर्स की गिनती के आधार पर और उपयोग करके बैरियर को संकेत देते हैं। cond.Wait() cond.Broadcast() प्रत्येक वर्कर गोरूटीन कुछ काम करता है और फिर काउंटर वैरिएबल को बढ़ाने के लिए लॉक प्राप्त करता है। यदि वर्तमान वर्कर बैरियर तक पहुँचने वाला अंतिम व्यक्ति है, तो यह सभी प्रतीक्षारत वर्करों को जगाने के लिए का उपयोग करके बैरियर की स्थिति को प्रसारित करता है। अन्यथा, यह अंतिम वर्कर द्वारा अधिसूचित किए जाने के लिए का उपयोग करके बैरियर पर प्रतीक्षा करता है। cond.Broadcast() cond.Wait() बैरियर सिंक्रोनाइजेशन यह सुनिश्चित करता है कि सभी वर्कर गोरूटीन बैरियर तक पहुंचें, इससे पहले कि उनमें से कोई भी उससे आगे बढ़े। यह उन परिदृश्यों में उपयोगी हो सकता है, जिनमें वर्कफ़्लो में किसी विशिष्ट बिंदु पर कई गोरूटीन के निष्पादन को सिंक्रोनाइज़ करने की आवश्यकता होती है। ध्यान दें कि इस उदाहरण में बैरियर को एक सरल काउंटर का उपयोग करके लागू किया गया है। हालाँकि, अधिक जटिल परिदृश्यों में, आपको सही सिंक्रोनाइज़ेशन सुनिश्चित करने और रेस स्थितियों से बचने के लिए अतिरिक्त सिंक्रोनाइज़ेशन तंत्र या शर्तों पर विचार करने की आवश्यकता हो सकती है। निष्कर्ष निष्कर्ष में, गो प्रोग्रामिंग भाषा में एक उपयोगी प्रकार है जो विशिष्ट स्थितियों के आधार पर गोरूटीन के बीच समन्वय और समन्वय की अनुमति देता है। यह स्थिति चर बनाने और प्रबंधित करने का एक तरीका प्रदान करता है। इसमें स्थितियों की प्रतीक्षा करने, संकेत देने और प्रसारित करने के तरीके हैं। `sync.Cond` का उपयोग करके, आप गो में अधिक नियंत्रित और सिंक्रनाइज़ समवर्ती प्रोग्राम लिख सकते हैं। sync.Cond यह ध्यान रखना महत्वपूर्ण है कि गो मानक लाइब्रेरी द्वारा प्रदान किए गए सिंक्रोनाइज़ेशन प्राइमेटिव में से एक है, और इसका उपयोग आपके समवर्ती कार्यक्रम की विशिष्ट आवश्यकताओं पर निर्भर करता है। कुछ मामलों में, चैनल या जैसे अन्य सिंक्रोनाइज़ेशन प्राइमेटिव अधिक उपयुक्त हो सकते हैं। sync.Cond sync.WaitGroup