सेमाफोर - प्रारंभिक गणना का उपयोग क्या है?


91

http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim.aspx

एक सेमाफोर बनाने के लिए, मुझे एक प्रारंभिक गिनती और अधिकतम गिनती प्रदान करने की आवश्यकता है। MSDN बताता है कि एक प्रारंभिक गिनती है -

सेमाफोर के लिए अनुरोधों की प्रारंभिक संख्या जो समवर्ती रूप से दी जा सकती है।

जबकि यह बताता है कि अधिकतम गिनती है

सेमाफोर के लिए अनुरोधों की अधिकतम संख्या जो समवर्ती रूप से दी जा सकती है।

मैं समझ सकता हूं कि अधिकतम गिनती थ्रेड्स की अधिकतम संख्या है जो किसी संसाधन को समवर्ती रूप से एक्सेस कर सकती है। लेकिन, प्रारंभिक गिनती का उपयोग क्या है?

यदि मैं 0 की प्रारंभिक गिनती और 2 की अधिकतम गणना के साथ एक अर्ध-कवच बनाता हूं, तो मेरा कोई भी थ्रेड सूत्र संसाधन तक पहुंचने में सक्षम नहीं है। यदि मैंने प्रारंभिक गणना को 1 और अधिकतम गिनती को 2 के रूप में सेट किया है, तो केवल थ्रेड पूल थ्रेड संसाधन तक पहुंच सकता है। यह केवल तब होता है जब मैं प्रारंभिक गिनती और अधिकतम संख्या दोनों को 2 के रूप में सेट करता हूं, 2 सूत्र समवर्ती रूप से संसाधन तक पहुंचने में सक्षम होते हैं। तो, मैं वास्तव में प्रारंभिक गिनती के महत्व के बारे में उलझन में हूं?

SemaphoreSlim semaphoreSlim = new SemaphoreSlim(0, 2); //all threadpool threads wait
SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 2);//only one thread has access to the resource at a time
SemaphoreSlim semaphoreSlim = new SemaphoreSlim(2, 2);//two threadpool threads can access the resource concurrently

7
कैसे आया आपने SVGreg का जवाब कभी नहीं स्वीकार किया?
जॉन

जवाबों:


79

हां, जब प्रारंभिक संख्या 0 पर सेट हो जाती है - "करंटकाउंट" संपत्ति को बढ़ाते समय सभी धागे इंतजार कर रहे होंगे। आप इसे रिलीज़ () या रिलीज़ (Int32) के साथ कर सकते हैं।

रिलीज (...) - सेमाफोर काउंटर में वृद्धि होगी

रुको (...) - इसे घटाएंगे

आप काउंटर ("करंटकाउंट" प्रॉपर्टी) को अधिकतम गिनती से अधिक नहीं बढ़ा सकते हैं जिसे आपने इनिशियलाइज़ेशन में सेट किया है।

उदाहरण के लिए:

SemaphoreSlim^ s = gcnew SemaphoreSlim(0,2); //s->CurrentCount = 0
s->Release(2); //s->CurrentCount = 2
...

s->Wait(); //Ok. s->CurrentCount = 1
...

s->Wait(); //Ok. s->CurrentCount = 0
...

s->Wait(); //Will be blocked until any of the threads calls Release()

1
आपका कोड बेहतर तरीके से टिप्पणी के बजाय उत्तर में प्रस्तुत किया जाएगा।
ChrisF

14
LOL यह संभवत: 5 वीं बार है कि मैं इसी उत्तर तक पहुंचता हूं क्योंकि निर्माता का प्रलेखन हमेशा मुझे भ्रमित करता है कि किन मूल्यों को सेट करना है। चीयर्स
ब्लू स्ट्रैट

70

तो, मैं वास्तव में प्रारंभिक गिनती के महत्व के बारे में उलझन में हूं?

एक महत्वपूर्ण बिंदु जो यहां मदद कर सकता है वह यह है कि Waitसेमीफोर काउंट को घटाता है और Releaseइसे बढ़ाता है।

initialCountसंसाधन पहुंच की संख्या है जिसे तुरंत अनुमति दी जाएगी। या, दूसरे शब्दों में, यह समय की संख्या Waitहै जिसे सेमीफ़ायर के तुरंत बाद अवरुद्ध किए बिना कहा जा सकता है।

maximumCountसबसे अधिक गिनती जो अर्धचालक प्राप्त कर सकता है। यह कई बार Releaseबिना किसी अपवाद के initialCountगणना शून्य कहे जाने पर फेंकने की संख्या है। यदि initialCountउसी मूल्य पर सेट किया गया है, maximumCountतो सेमीफ़ायर के Releaseतुरंत बाद कॉल करने पर अपवाद छोड़ दिया जाएगा।


20
यह कितना मददगार है! मैं सेमाफोरस के बारे में सोच रहा था कि पिछड़े हुए हैं, क्योंकि शुरुआती समय में शुरुआती ब्लॉक संसाधनों की संख्या थी, न कि तुरंत उपलब्ध संसाधनों की संख्या। धन्यवाद।
फिलिप टेन

5
@PhilipTenn, मैं मानता हूं - इस संबंध में प्रलेखन स्पष्ट नहीं है
ब्लूस्टैट

मैं सहमत था, उन्हें उस परिवर्तनशील नाम को बदलना चाहिए या डॉक्स को अपडेट करना चाहिए
आयरनहाइड

@ सैंडबॉक्स आपको इस उत्तर IMO को स्वीकार करना चाहिए, क्योंकि यह वास्तव में initialCountपैरामीटर का अर्थ बताता है ।
10

8

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

(दो कंस्ट्रक्टर हैं: एक जो केवल एक प्रारंभिक मूल्य लेता है, और एक जो अतिरिक्त रूप से अधिकतम गिनती लेता है। जो भी उपयुक्त हो उपयोग करें।)


1

इस तरह से जब वर्तमान धागा सेमाफोर बनाता है तो यह शुरू से ही कुछ संसाधनों का दावा कर सकता है।


तो, आपका मतलब है कि जब मैं संसाधन को एक्सेस करने के लिए दो वर्कर थ्रेड चाहता हूं तो मुझे शुरुआती गिनती बदलनी चाहिए?
सैंडबॉक्स

यह वर्तमान धागा है जो एक गिनती का दावा करता है। यदि आप नहीं चाहते हैं कि वर्तमान थ्रेड किसी भी एक्सेस पास 0 का दावा करे या एक पैरामीटर के साथ अधिभार का उपयोग करे।
एरनो

1

यदि आप चाहते हैं कि कोई भी धागा आपके संसाधन को कुछ समय तक एक्सेस न करे, तो आप प्रारंभिक गणना को 0 के रूप में पास करते हैं और जब आप सभी को सेमीफोर बनाने के बाद उन सभी तक पहुँच प्रदान करना चाहते हैं, तो आप अधिकतम गिनती के बराबर प्रारंभिक गणना का मान पास करते हैं । उदाहरण के लिए:

hSemaphore = CreateSemaphoreA(NULL, 0, MAX_COUNT, NULL) ;

//Do something here
//No threads can access your resource

ReleaseSemaphore(hSemaphore, MAX_COUNT, 0) ;

//All threads can access the resource now

जैसा कि एमएसडीएन डॉक्यूमेंटेशन में उद्धृत किया गया है- "रिलीजस्मैफोर का एक और उपयोग एक एप्लिकेशन के इनिशियलाइजेशन के दौरान है। एप्लिकेशन शून्य की प्रारंभिक गणना के साथ एक सेमाफोर बना सकता है। यह सेमीफोर की स्थिति को nonsignaled पर सेट करता है और सभी थ्रेड्स को संरक्षित संसाधन तक पहुँचने से रोकता है। इसकी आरंभिकता को पूरा करता है, संरक्षित संसाधन तक सामान्य पहुंच की अनुमति देने के लिए, यह अपने अधिकतम मूल्य तक गिनती बढ़ाने के लिए रिलीजसेमफोर का उपयोग करता है। "


क्षमा करें, मैंने आपको C ++ में उदाहरण दिया है, हालांकि संदेह स्पष्ट कर सकता है।
अभिनेत

0

संसाधनों के एक पूल की सुरक्षा के लिए सेमाफोर का उपयोग किया जा सकता है । हम संसाधन पूल का उपयोग उन चीजों के पुन: उपयोग के लिए करते हैं जो बनाने के लिए महंगी हैं - जैसे डेटाबेस कनेक्शन।

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

प्रारंभिक गिनती के महत्व के बारे में मैं वास्तव में भ्रमित हूं?

Initial count = Upfront cost

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

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


-1

जैसा कि MSDN ने रिमार्क्स सेक्शन के तहत बताया है:

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

इसलिए यदि प्रारंभिक गिनती 0 है और अधिकतम 2 है तो यह है कि WaitOne को मुख्य धागे से दो बार कॉल किया गया है, इसलिए हम क्षमता तक पहुंच गए हैं (सेमीफोर काउंट 0 है) और कोई भी धागा सेमीफोर में प्रवेश नहीं कर सकता है। इसी तरह यदि प्रारंभिक गिनती 1 है और अधिकतम 2 है तो वेटऑन को एक बार कॉल किया गया है और केवल एक धागा प्रवेश कर सकता है इससे पहले कि हम फिर से क्षमता तक पहुंच सकें।

यदि 0 का उपयोग प्रारंभिक गणना के लिए किया जाता है, तो हम संसाधन को प्राप्त करने के लिए अधिकतम संख्या में थ्रेड्स की अनुमति देने के लिए सेमाफोर गणना को अधिकतम करने के लिए रिलीज़ (2) को हमेशा कॉल कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.