2010-03-19 3 views
15

मैं शर्त चर के बारे में जानने की कोशिश कर रहा हूं। मैं जानना चाहता हूं कि सामान्य परिस्थितियां क्या हैं जहां हालत चर का उपयोग किया जाता है।सी ++ में हालत चर के सामान्य उपयोग क्या हैं?

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

अन्य डिज़ाइन स्थितियां कहां हैं जहां आपको एक कंडीशन वैरिएबल की आवश्यकता होती है?

मैं अनुभव से आधारित उदाहरण पसंद करूंगा, जैसे असली लाइव एप्लिकेशन में।

+1

क्या यह समुदाय विकी होना चाहिए? – jasonline

+0

चूंकि आप एक विशिष्ट उत्तर की तलाश नहीं कर रहे हैं और शायद अधिक सामान्य "उत्तर", शायद। लेकिन मैं इस की बाड़ पर अधिक हूं, आप दूसरों से ना या यारे की प्रतीक्षा कर सकते हैं। – GManNickG

+2

+1 इस अच्छे प्रश्न के लिए आप अच्छी तरह से अर्जित प्रतिष्ठा अंक लें :-) –

उत्तर

2

हालत चर के एक उपयोग जो कि केवल एक संदेश कतार की तुलना में थोड़ा अधिक जटिल है, "लॉक साझा करें" है, जहां विभिन्न धागे समान मूल प्रकृति की अलग-अलग स्थितियों के लिए प्रतीक्षा कर रहे हैं। उदाहरण के लिए, आपके पास एक (बहुत शर्मीली, सरलीकृत) वेब कैश है। कैश में प्रत्येक प्रविष्टि में तीन संभावित राज्य होते हैं: उपस्थित नहीं, IN_PROGRESS, पूर्ण।

getURL: 
    lock the cache 
    three cases for the key: 
     not present: 
      add it (IN_PROGRESS) 
      release the lock 
      fetch the URL 
      take the lock 
      update to COMPLETE and store the data 
      broadcast the condition variable 
      goto COMPLETE 
     COMPLETE: 
      release the lock and return the data 
     IN_PROGRESS: 
      while (still IN_PROGRESS): 
       wait on the condition variable 
      goto COMPLETE 

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

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

1

एक उदाहरण, उपभोक्ता-निर्माता मॉडल के अतिरिक्त, जिसे आपने पहले ही उल्लेख किया है, barrier synchronization में उपयोग है। जब धागे अवरोध में प्रवेश करते हैं, यदि बाधा में प्रवेश करने की आवश्यकता वाले अन्य धागे हैं, तो वे एक शर्त चर पर प्रतीक्षा करते हैं। बाधा दर्ज करने के लिए अंतिम धागा स्थिति संकेत करता है।

+0

@ माइकल: मैं बाधाओं से वास्तव में परिचित नहीं हूं ... लेकिन आपके उदाहरण में, क्या आप कह रहे हैं कि आपने अलग स्थिति चर के साथ बाधाओं का उपयोग किया है? मैंने सोचा कि आप अकेले बाधाओं का उपयोग कर उपर्युक्त स्थिति को कार्यान्वित कर सकते हैं और एक अलग स्थिति चर की आवश्यकता नहीं है? – jasonline

+0

@ जेसनलाइन, इसलिए, आप pthreads द्वारा प्रदान की गई बाधाओं का उपयोग कर सकते हैं, लेकिन आप एक म्यूटेक्स और एक कंडीशन वैरिएबल का उपयोग करके अपने बाधा को भी कार्यान्वित कर सकते हैं (जो कि सबसे अधिक संभावना है कि वह अपने आप को कैसे प्रदान करता है)। जब आप बाधा डालते हैं, तो आप म्यूटेक्स को लॉक करते हैं, गिनती बढ़ाते हैं, और बाधा समझ को स्टोर करते हैं। यदि गिनती अधिकतम तक पहुंच गई है, तो आप गिनती को शून्य पर रीसेट कर देते हैं, बाधा समझ को उलट देते हैं, हालत को सिग्नल करते हैं, और बाधा से बाहर निकलते हैं। अन्यथा, आप इस स्थिति पर इंतजार करते हैं, जब तक बाधा भावना संग्रहीत किसी के विपरीत न हो। –

+0

आह, हाँ। मुझे आपका बिंदु पता है। धन्यवाद। – jasonline

0

मैंने इसे सिंक्रनाइज़ किए गए संदेश भेजने के लिए उपयोग किया, जहां एक सिंक-ऑब्जेक्ट जोड़ा गया था।
सिंक ऑब्जेक्ट में "तैयार" बूलियन के साथ एक शर्त चर शामिल था।
syncMsg :: send() फ़ंक्शन में, एक सिंक-> प्रतीक्षा() और syncMsg :: हैंडल() फ़ंक्शन में, एक सिंक-> go() था।

संभावित डेडलॉक्स के कारण उचित रूप से उपयोग किया जाना चाहिए।

0

मैं त्रुटि-प्रवण Win32 इवेंट ऑब्जेक्ट्स की बजाय स्थिति चर का उपयोग करता हूं। कंडवर्स के साथ, आपको नकली संकेत के बारे में चिंता करने की ज़रूरत नहीं है। कई घटनाओं के होने का इंतजार करना भी आसान है।

कोंडवार्स सेफफोर्स को भी बदल सकते हैं, क्योंकि वे अधिक सामान्य उद्देश्य हैं।

0

मुझे पता है कि यह बहुत उपयोगी नहीं है, लेकिन जब भी मैं थ्रेड चाहता हूं कि कुछ घटित होने के लिए प्रतीक्षा करें, या केवल कुछ होने तक प्रतीक्षा करें।

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

पृष्ठभूमि धागा इस बुनियादी तर्क

void threadFunction() { 
    initialisation(); 

    while(! shutdown()) { 
     backgroundTask(); 

     shutdown_condition_wait(timeout_value); 
    } 

    cleanup(); 
} 

इस पृष्ठभूमि धागा बंद तुरंत और शान से की सुविधा देता है इस प्रकार है।

यदि मेरे पास ऐसे कई धागे हैं तो मुख्य फ़ंक्शन प्रत्येक को बंद करने के लिए सिग्नल करता है तो अगले के बाद प्रत्येक में शामिल होता है। यह प्रत्येक थ्रेड घटक को समानांतर में बंद करने में सक्षम बनाता है।