सशर्त चर बनाम सेमाफोर


110

किसी को एक सेमाफोर का उपयोग कब करना चाहिए और कब एक सशर्त चर (CondVar) का उपयोग करना चाहिए?


1
संबंधित जानकारी लिंक stackoverflow.com/questions/4039899/… पर
कार्तिक बालगुरु

जवाबों:


207

आपसी बहिष्कार के लिए ताले का उपयोग किया जाता है। जब आप यह सुनिश्चित करना चाहते हैं कि कोड का एक टुकड़ा परमाणु है, तो उसके चारों ओर एक ताला लगा दें। आप ऐसा करने के लिए सैद्धांतिक रूप से एक बाइनरी सेमाफोर का उपयोग कर सकते हैं, लेकिन यह एक विशेष मामला है।

सेमाफोर और कंडीशन वैरिएबल ताले द्वारा प्रदान किए गए पारस्परिक बहिष्करण के शीर्ष पर निर्मित होते हैं और साझा संसाधनों के लिए सिंक्रनाइज़ एक्सेस प्रदान करने के लिए उपयोग किए जाते हैं। उनका उपयोग समान उद्देश्यों के लिए किया जा सकता है।

एक स्थिति चर का उपयोग आम तौर पर व्यस्त प्रतीक्षा से बचने के लिए किया जाता है (किसी स्थिति की जांच करते समय बार-बार लूपिंग) जब तक कि संसाधन उपलब्ध होने की प्रतीक्षा न हो। उदाहरण के लिए, यदि आपके पास एक धागा (या कई धागे) हैं जो तब तक आगे नहीं बढ़ सकते हैं जब तक कि एक कतार खाली नहीं होती है, तब तक प्रतीक्षा में व्यस्त दृष्टिकोण कुछ ऐसा करना होगा:

//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()सेमाफोर के संचालन।

निश्चित रूप से दोनों विकल्पों के बीच ओवरलैप है। ऐसे कई परिदृश्य हैं जहां एक अर्ध-संस्करण या एक स्थिति चर (या स्थिति चर का सेट) दोनों आपके उद्देश्यों की सेवा कर सकते हैं। दोनों सेमाफोर और कंडीशन वैरिएबल एक लॉक ऑब्जेक्ट के साथ जुड़े हुए हैं जिसका उपयोग वे पारस्परिक बहिष्कार बनाए रखने के लिए करते हैं, लेकिन फिर वे थ्रेड निष्पादन को सिंक्रनाइज़ करने के लिए लॉक के शीर्ष पर अतिरिक्त कार्यक्षमता प्रदान करते हैं। यह आप पर निर्भर करता है कि आपकी स्थिति के लिए कौन सबसे अधिक मायने रखता है।

यह जरूरी नहीं कि सबसे तकनीकी विवरण है, लेकिन यह है कि यह कैसे मेरे सिर में समझ में आता है।


9
महान जवाब, मैं अन्य उत्तरों से जोड़ना चाहूंगा: सेमाफोर का उपयोग थ्रेड्स निष्पादित करने की संख्या को नियंत्रित करने के लिए किया जाता है। संसाधनों का निश्चित सेट होगा। जब एक धागा समान होता है तो संसाधन गणना हर बार घट जाती है। जब सेमाफोर की गिनती 0 तक पहुंच जाती है, तो संसाधन को हासिल करने के लिए किसी अन्य धागे की अनुमति नहीं होती है। संसाधन थ्रेडिंग जारी होने तक थ्रेड्स अवरुद्ध हो जाते हैं। संक्षेप में, मुख्य अंतर यह है कि एक ही बार में कितने थ्रेड्स संसाधन प्राप्त करने की अनुमति दी जाती है? म्यूटेक्स - एक। सेमाफोर - इसका DEFINED_COUNT, (जितने भी सेमाफोर काउंट हैं)
berkay

10
बस इस बात पर विस्तार से बताएं कि लूप के बजाय यह सरल क्यों है: स्प्यूरिओस वेकूप नाम की कोई चीजइस विकिपीडिया लेख का हवाला देते हुए : "इसके कारणों में से एक स्पिरिट वेकअप है; अर्थात, इसकी प्रतीक्षा स्थिति से एक धागा जाग सकता है, भले ही कोई थ्रेड स्थिति चर संकेत दे"
व्लादिस्लाव्स बुरकोवस

3
@VladislavsBurakovs अच्छी बात है! मुझे लगता है कि यह उस स्थिति के लिए भी उपयोगी है जहाँ एक प्रसारण अधिक थ्रेड बनाता है, जहाँ उपलब्ध संसाधन हैं (उदाहरण के लिए 3 थ्रेड्स को प्रसारित करता है, लेकिन कतार में केवल 2 आइटम हैं)।
ब्रेंट राइट्स कोड

काश मैं कतार के पूर्ण होने तक आपको जवाब देता;) सही उत्तर। यह कोड semaphores csc.villanova.edu/~mdamian/threads/PC.htm का
मोहम्मद-जाफर NEHME

3
@VladislavsBurakovs थोड़ा स्पष्ट करने के लिए, कारण यह है कि हालत अभी भी एक धागे के लिए झूठी हो सकती है जो अभी जाग गई है (परिणामस्वरूप एक अजीब जागरण) यह है कि धागा को स्थिति की जांच करने का मौका मिलने से पहले एक संदर्भ स्विच हो सकता है। फिर, जहां कुछ अन्य अनुसूचित धागे ने उस स्थिति को झूठा बना दिया। यह एक कारण है कि मैं एक अजीबोगरीब जागरण के लिए जानता हूं, यह नहीं जानता कि क्या अधिक हैं।
अधिकतम

52

आइए जानें कि हुड के नीचे क्या है।

सशर्त चर अनिवार्य रूप से एक प्रतीक्षा-कतार है , जो अवरुद्ध-प्रतीक्षा और वेकअप संचालन का समर्थन करता है, यानी आप प्रतीक्षा-कतार में एक धागा डाल सकते हैं और इसके राज्य को ब्लॉक कर सकते हैं, और इससे एक धागा प्राप्त कर सकते हैं और READY पर अपना राज्य सेट कर सकते हैं।

ध्यान दें कि एक सशर्त चर का उपयोग करने के लिए, दो अन्य तत्वों की आवश्यकता होती है:

  • एक शर्त (आमतौर पर एक ध्वज या काउंटर की जाँच करके लागू की जाती है)
  • एक म्यूटेक्स जो स्थिति को बचाता है

प्रोटोकॉल फिर बन जाता है,

  1. म्यूटेक्स का अधिग्रहण करें
  2. स्थिति की जाँच करें
  3. ब्लॉक और रिलीज म्यूटेक्स यदि स्थिति सही है, तो म्यूटेक्स को छोड़ दें

सेमाफोर अनिवार्य रूप से एक काउंटर + म्यूटेक्स + एक प्रतीक्षा कतार है। और इसका उपयोग किया जा सकता है क्योंकि यह बाहरी निर्भरता के बिना है। आप इसे म्यूटेक्स के रूप में या सशर्त चर के रूप में उपयोग कर सकते हैं।

इसलिए, सेमाफोर को सशर्त चर की तुलना में अधिक परिष्कृत संरचना के रूप में माना जा सकता है, जबकि बाद वाला अधिक हल्का और लचीला है।


म्यूटेक्स को एक स्थिति चर के रूप में देखा जा सकता है, यह शर्त है कि पकड़ की जाए या नहीं।
宏杰 宏杰

18

सेमाफोर का उपयोग चर तक विशेष पहुंच को लागू करने के लिए किया जा सकता है, हालांकि उनका उपयोग सिंक्रनाइज़ेशन के लिए किया जाना है। दूसरी ओर, म्यूटेक्स के पास एक शब्दार्थ है जो कड़ाई से पारस्परिक बहिष्कार से संबंधित है: केवल प्रक्रिया जो संसाधन को लॉक करती है, उसे अनलॉक करने की अनुमति है।

दुर्भाग्य से आप म्यूटेक्स के साथ सिंक्रोनाइज़ेशन को लागू नहीं कर सकते, इसीलिए हमारे पास कंडीशन वैरिएबल हैं। यह भी ध्यान दें कि कंडीशन वेरिएबल्स के साथ आप ब्रॉडकास्टिंग अनलॉकिंग का उपयोग करके एक ही पल में सभी वेटिंग थ्रेड्स को अनलॉक कर सकते हैं। यह सेमाफोर के साथ नहीं किया जा सकता है।


9

सेमाफोर और कंडीशन वैरिएबल बहुत समान हैं और ज्यादातर एक ही उद्देश्य के लिए उपयोग किए जाते हैं। हालांकि, ऐसे छोटे अंतर हैं जो किसी को बेहतर बना सकते हैं। उदाहरण के लिए, बैरियर सिंक्रोनाइज़ेशन को लागू करने के लिए आप एक सेमाफोर का उपयोग नहीं कर पाएंगे। लेकिन एक स्थिति चर आदर्श है।

बैरियर सिंक्रोनाइज़ेशन तब होता है जब आप चाहते हैं कि आपके सभी धागे तब तक प्रतीक्षा करें जब तक कि सभी थ्रेड फ़ंक्शन में एक निश्चित भाग पर नहीं आ जाते। इसे एक स्थैतिक चर के द्वारा लागू किया जा सकता है जो शुरू में उस धागे तक पहुंचने पर प्रत्येक थ्रेड द्वारा घटित कुल थ्रेड का मान है। इसका मतलब यह है कि हम चाहते हैं कि प्रत्येक धागा सोने के लिए जब तक कि आखिरी न आ जाए। सेमाफोर सटीक विपरीत करेगा! एक सेमाफोर के साथ, प्रत्येक धागा चालू रहेगा और अंतिम धागा (जो सेमाफोर मान को 0 पर सेट करेगा) सो जाएगा।

दूसरी ओर एक स्थिति चर, आदर्श है। जब प्रत्येक थ्रेड बाधा की ओर जाता है तो हम जाँचते हैं कि हमारा स्थिर काउंटर शून्य है या नहीं। यदि नहीं, तो हम स् थ्रेड को स्लीप को वेरिएबल वैरिएबल फंक्शन के साथ सेट करते हैं। जब आखिरी धागा अवरोध पर आ जाता है, तो काउंटर मान शून्य हो जाएगा और यह अंतिम धागा स्थिति चर सिग्नल फ़ंक्शन को कॉल करेगा जो अन्य सभी थ्रेड्स को जगाएगा!


1

मैं मॉनिटर सिंक्रोनाइज़ेशन के तहत कंडीशन वैरिएबल फाइल करता हूं। मैंने आम तौर पर अर्धवृत्त और मॉनिटर को दो अलग-अलग सिंक्रनाइज़ेशन शैलियों के रूप में देखा है। दोनों के बीच इस बात को लेकर मतभेद हैं कि राज्य का डेटा कितना स्वाभाविक रूप से रखा गया है और आप कोड कैसे मॉडल करना चाहते हैं - लेकिन वास्तव में कोई समस्या नहीं है जिसे एक नहीं बल्कि दूसरे द्वारा हल किया जा सकता है।

मैं मॉनिटर फॉर्म की ओर कोड करता हूं; अधिकांश भाषाओं में मैं इसमें काम करता हूं म्यूटेक्स, स्थिति चर, और कुछ बैकिंग स्टेट चर। लेकिन सेमाफोर काम भी करेंगे।


2
यह एक बेहतर उत्तर होगा यदि आपने समझाया कि "मॉनिटर फॉर्म" क्या है।
स्टीवन लू

0

mutexऔर conditional variablesसे लिए गए हैं semaphore

  • के लिए mutex, semaphoreदो राज्यों का उपयोग करता है: 0, 1
  • के लिए उपयोग करता है काउंटर।condition variablessemaphore

वे सिंटैक्टिक शुगर की तरह हैं


C ++ std लाइब्रेरी में वे सभी जिला ऑब्जेक्ट हैं, सभी को प्लेटफॉर्म विशिष्ट API का उपयोग करके लागू किया गया है। निश्चित रूप से एक सेमाफोर संकेतित समय की संख्या को अनब्लॉक करेगा, हालत चर को कई बार संकेत दिया जा सकता है लेकिन केवल एक बार अनब्लॉक करें। यही कारण है कि वैर एक म्यूटेक्स को एक पैरामीटर के रूप में लेता है।
doron
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.