जवाबों:
आपसी बहिष्कार के लिए ताले का उपयोग किया जाता है। जब आप यह सुनिश्चित करना चाहते हैं कि कोड का एक टुकड़ा परमाणु है, तो उसके चारों ओर एक ताला लगा दें। आप ऐसा करने के लिए सैद्धांतिक रूप से एक बाइनरी सेमाफोर का उपयोग कर सकते हैं, लेकिन यह एक विशेष मामला है।
सेमाफोर और कंडीशन वैरिएबल ताले द्वारा प्रदान किए गए पारस्परिक बहिष्करण के शीर्ष पर निर्मित होते हैं और साझा संसाधनों के लिए सिंक्रनाइज़ एक्सेस प्रदान करने के लिए उपयोग किए जाते हैं। उनका उपयोग समान उद्देश्यों के लिए किया जा सकता है।
एक स्थिति चर का उपयोग आम तौर पर व्यस्त प्रतीक्षा से बचने के लिए किया जाता है (किसी स्थिति की जांच करते समय बार-बार लूपिंग) जब तक कि संसाधन उपलब्ध होने की प्रतीक्षा न हो। उदाहरण के लिए, यदि आपके पास एक धागा (या कई धागे) हैं जो तब तक आगे नहीं बढ़ सकते हैं जब तक कि एक कतार खाली नहीं होती है, तब तक प्रतीक्षा में व्यस्त दृष्टिकोण कुछ ऐसा करना होगा:
//pseudocode
while(!queue.empty())
{
sleep(1);
}
इसके साथ समस्या यह है कि आप इस थ्रेड को बार-बार स्थिति की जाँच करके प्रोसेसर समय बर्बाद कर रहे हैं। इसके बजाय एक तुल्यकालन चर क्यों नहीं है जो कि संसाधन उपलब्ध होने वाले धागे को बताने के लिए संकेत किया जा सकता है?
//pseudocode
syncVar.lock.acquire();
while(!queue.empty())
{
syncVar.wait();
}
//do stuff with queue
syncVar.lock.release();
मुमकिन है, आपके पास एक धागा कहीं और होगा जो चीजों को कतार से बाहर खींच रहा है। जब कतार खाली होती है, तो यह syncVar.signal()
एक यादृच्छिक थ्रेड को जगाने के लिए कॉल कर सकता है जो सो रहा है syncVar.wait()
(या आमतौर पर प्रतीक्षा कर रहे सभी थ्रेड्स को जगाने के लिए एक विधि signalAll()
या broadcast()
विधि भी है )।
मैं आमतौर पर इस तरह के सिंक्रनाइज़ेशन चर का उपयोग करता हूं जब मेरे पास एक या एक से अधिक धागे एक विशेष स्थिति पर इंतजार कर रहे होते हैं (जैसे कतार खाली होने के लिए)।
सेमाफोर समान रूप से उपयोग किया जा सकता है, लेकिन मुझे लगता है कि जब आप एक साझा संसाधन उपलब्ध हो सकते हैं और उपलब्ध चीजों के पूर्णांक संख्या के आधार पर उपलब्ध नहीं हो सकते हैं, तो वे बेहतर उपयोग करते हैं। निर्माता / उपभोक्ता स्थितियों के लिए सेमाफोरेस अच्छे हैं, जहां उत्पादक संसाधनों का आवंटन कर रहे हैं और उपभोक्ता उनका उपभोग कर रहे हैं।
इस बारे में सोचें कि क्या आपके पास सोडा वेंडिंग मशीन है। केवल एक सोडा मशीन है और यह एक साझा संसाधन है। आपके पास एक धागा है जो एक विक्रेता (निर्माता) है जो मशीन को स्टॉक रखने के लिए जिम्मेदार है और एन धागे जो खरीदार (उपभोक्ता) हैं जो मशीन से सोडा प्राप्त करना चाहते हैं। मशीन में सोडा की संख्या पूर्णांक मान है जो हमारे सेमाफोर को चलाएगी।
सोडा मशीन में आने वाला हर खरीदार (उपभोक्ता) धागा सोडा down()
लेने के लिए सेमाफोर पद्धति को कहता है । यह मशीन से एक सोडा लेगा और 1. द्वारा उपलब्ध सोडा की गिनती में कमी करेगा। यदि सोडा उपलब्ध हैं, तो कोड सिर्फ down()
एक समस्या के बिना बयान को चालू रखेगा । यदि कोई सोडा उपलब्ध नहीं है, तो थ्रेड सो जाएगा जब सोडा फिर से उपलब्ध होने पर सूचित किया जाएगा (जब मशीन में अधिक सोडा होते हैं)।
वेंडर (निर्माता) धागा अनिवार्य रूप से सोडा मशीन के खाली होने का इंतजार कर रहा होगा। जब अंतिम सोडा मशीन से लिया जाता है (और एक या अधिक उपभोक्ता संभावित रूप से सोडा बाहर निकलने की प्रतीक्षा कर रहे हैं) तो विक्रेता को सूचित किया जाता है। विक्रेता सोडा मशीन को सेमाफोर up()
विधि से फिर से स्थापित करेगा, सोडा की उपलब्ध संख्या हर बार बढ़ाई जाएगी और जिससे प्रतीक्षा करने वाले उपभोक्ता धागे को सूचित किया जाएगा कि अधिक सोडा उपलब्ध है।
wait()
और signal()
एक तुल्यकालन चर के तरीकों के भीतर छिपा हो जाते हैं down()
और up()
सेमाफोर के संचालन।
निश्चित रूप से दोनों विकल्पों के बीच ओवरलैप है। ऐसे कई परिदृश्य हैं जहां एक अर्ध-संस्करण या एक स्थिति चर (या स्थिति चर का सेट) दोनों आपके उद्देश्यों की सेवा कर सकते हैं। दोनों सेमाफोर और कंडीशन वैरिएबल एक लॉक ऑब्जेक्ट के साथ जुड़े हुए हैं जिसका उपयोग वे पारस्परिक बहिष्कार बनाए रखने के लिए करते हैं, लेकिन फिर वे थ्रेड निष्पादन को सिंक्रनाइज़ करने के लिए लॉक के शीर्ष पर अतिरिक्त कार्यक्षमता प्रदान करते हैं। यह आप पर निर्भर करता है कि आपकी स्थिति के लिए कौन सबसे अधिक मायने रखता है।
यह जरूरी नहीं कि सबसे तकनीकी विवरण है, लेकिन यह है कि यह कैसे मेरे सिर में समझ में आता है।
आइए जानें कि हुड के नीचे क्या है।
सशर्त चर अनिवार्य रूप से एक प्रतीक्षा-कतार है , जो अवरुद्ध-प्रतीक्षा और वेकअप संचालन का समर्थन करता है, यानी आप प्रतीक्षा-कतार में एक धागा डाल सकते हैं और इसके राज्य को ब्लॉक कर सकते हैं, और इससे एक धागा प्राप्त कर सकते हैं और READY पर अपना राज्य सेट कर सकते हैं।
ध्यान दें कि एक सशर्त चर का उपयोग करने के लिए, दो अन्य तत्वों की आवश्यकता होती है:
प्रोटोकॉल फिर बन जाता है,
सेमाफोर अनिवार्य रूप से एक काउंटर + म्यूटेक्स + एक प्रतीक्षा कतार है। और इसका उपयोग किया जा सकता है क्योंकि यह बाहरी निर्भरता के बिना है। आप इसे म्यूटेक्स के रूप में या सशर्त चर के रूप में उपयोग कर सकते हैं।
इसलिए, सेमाफोर को सशर्त चर की तुलना में अधिक परिष्कृत संरचना के रूप में माना जा सकता है, जबकि बाद वाला अधिक हल्का और लचीला है।
सेमाफोर का उपयोग चर तक विशेष पहुंच को लागू करने के लिए किया जा सकता है, हालांकि उनका उपयोग सिंक्रनाइज़ेशन के लिए किया जाना है। दूसरी ओर, म्यूटेक्स के पास एक शब्दार्थ है जो कड़ाई से पारस्परिक बहिष्कार से संबंधित है: केवल प्रक्रिया जो संसाधन को लॉक करती है, उसे अनलॉक करने की अनुमति है।
दुर्भाग्य से आप म्यूटेक्स के साथ सिंक्रोनाइज़ेशन को लागू नहीं कर सकते, इसीलिए हमारे पास कंडीशन वैरिएबल हैं। यह भी ध्यान दें कि कंडीशन वेरिएबल्स के साथ आप ब्रॉडकास्टिंग अनलॉकिंग का उपयोग करके एक ही पल में सभी वेटिंग थ्रेड्स को अनलॉक कर सकते हैं। यह सेमाफोर के साथ नहीं किया जा सकता है।
सेमाफोर और कंडीशन वैरिएबल बहुत समान हैं और ज्यादातर एक ही उद्देश्य के लिए उपयोग किए जाते हैं। हालांकि, ऐसे छोटे अंतर हैं जो किसी को बेहतर बना सकते हैं। उदाहरण के लिए, बैरियर सिंक्रोनाइज़ेशन को लागू करने के लिए आप एक सेमाफोर का उपयोग नहीं कर पाएंगे। लेकिन एक स्थिति चर आदर्श है।
बैरियर सिंक्रोनाइज़ेशन तब होता है जब आप चाहते हैं कि आपके सभी धागे तब तक प्रतीक्षा करें जब तक कि सभी थ्रेड फ़ंक्शन में एक निश्चित भाग पर नहीं आ जाते। इसे एक स्थैतिक चर के द्वारा लागू किया जा सकता है जो शुरू में उस धागे तक पहुंचने पर प्रत्येक थ्रेड द्वारा घटित कुल थ्रेड का मान है। इसका मतलब यह है कि हम चाहते हैं कि प्रत्येक धागा सोने के लिए जब तक कि आखिरी न आ जाए। सेमाफोर सटीक विपरीत करेगा! एक सेमाफोर के साथ, प्रत्येक धागा चालू रहेगा और अंतिम धागा (जो सेमाफोर मान को 0 पर सेट करेगा) सो जाएगा।
दूसरी ओर एक स्थिति चर, आदर्श है। जब प्रत्येक थ्रेड बाधा की ओर जाता है तो हम जाँचते हैं कि हमारा स्थिर काउंटर शून्य है या नहीं। यदि नहीं, तो हम स् थ्रेड को स्लीप को वेरिएबल वैरिएबल फंक्शन के साथ सेट करते हैं। जब आखिरी धागा अवरोध पर आ जाता है, तो काउंटर मान शून्य हो जाएगा और यह अंतिम धागा स्थिति चर सिग्नल फ़ंक्शन को कॉल करेगा जो अन्य सभी थ्रेड्स को जगाएगा!
मैं मॉनिटर सिंक्रोनाइज़ेशन के तहत कंडीशन वैरिएबल फाइल करता हूं। मैंने आम तौर पर अर्धवृत्त और मॉनिटर को दो अलग-अलग सिंक्रनाइज़ेशन शैलियों के रूप में देखा है। दोनों के बीच इस बात को लेकर मतभेद हैं कि राज्य का डेटा कितना स्वाभाविक रूप से रखा गया है और आप कोड कैसे मॉडल करना चाहते हैं - लेकिन वास्तव में कोई समस्या नहीं है जिसे एक नहीं बल्कि दूसरे द्वारा हल किया जा सकता है।
मैं मॉनिटर फॉर्म की ओर कोड करता हूं; अधिकांश भाषाओं में मैं इसमें काम करता हूं म्यूटेक्स, स्थिति चर, और कुछ बैकिंग स्टेट चर। लेकिन सेमाफोर काम भी करेंगे।
mutex
और conditional variables
से लिए गए हैं semaphore
।
mutex
, semaphore
दो राज्यों का उपयोग करता है: 0, 1condition variables
semaphore
वे सिंटैक्टिक शुगर की तरह हैं