सेमफोरस्लीम के उपयोग को समझने की आवश्यकता है


95

यहाँ कोड है, लेकिन मुझे समझ नहीं आ रहा है कि क्या SemaphoreSlimकर रहा है।

async Task WorkerMainAsync()
{
    SemaphoreSlim ss = new SemaphoreSlim(10);
    List<Task> trackedTasks = new List<Task>();
    while (DoMore())
    {
        await ss.WaitAsync();
        trackedTasks.Add(Task.Run(() =>
        {
            DoPollingThenWorkAsync();
            ss.Release();
        }));
    }
    await Task.WhenAll(trackedTasks);
}

void DoPollingThenWorkAsync()
{
    var msg = Poll();
    if (msg != null)
    {
        Thread.Sleep(2000); // process the long running CPU-bound job
    }
}

इंतजार ss.WaitAsync();और क्या करता ss.Release();है?

मुझे लगता है कि अगर मैं एक बार में 50 थ्रेड चलाता हूं तो कोड लिखें SemaphoreSlim ss = new SemaphoreSlim(10);तो यह समय पर 10 सक्रिय थ्रेड चलाने के लिए मजबूर हो जाएगा।

जब 10 में से एक धागा पूरा हो जाएगा तो दूसरा धागा शुरू हो जाएगा। अगर मैं सही नहीं हूं तो मुझे नमूना स्थिति के साथ समझने में मदद करें।

awaitसाथ की आवश्यकता क्यों है ss.WaitAsync();? क्या करता ss.WaitAsync();है?


3
ध्यान देने वाली एक बात यह है कि आपको वास्तव में "DoPollingThenWorkAsync ();" "कोशिश {DoPollingThenWorkAsync ();} अंत में {ss.Release ();}", अन्यथा अपवाद स्थायी रूप से उस अर्धकुंभ को भुनाएंगे।
ऑस्टिन सालगट

मुझे थोड़ा अजीब लगता है कि हम क्रमशः कार्य के बाहर / अंदर अर्धकुंभ प्राप्त करते हैं और छोड़ते हैं। क्या "वेट ss.WaitAsync ()" कार्य के अंदर जाने से कोई फर्क पड़ेगा?
शेन लू

जवाबों:


77

मुझे लगता है कि अगर मैं एक बार में 50 धागा चलाता हूं तो सेमीफॉर्लीसम ss = new SemaphoreSlim (10) जैसे कोड; समय पर 10 सक्रिय धागे को चलाने के लिए मजबूर करेगा

वह सही है; सेमाफोर का उपयोग यह सुनिश्चित करता है कि एक ही समय में यह काम करने वाले 10 से अधिक कर्मचारी नहीं होंगे।

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

एक साइड नोट: पोस्टफ़िक्स DoPollingThenWorkAsyncनहीं होना चाहिए Asyncक्योंकि यह वास्तव में अतुल्यकालिक नहीं है, यह सिंक्रोनस है। जरा बुलाओ तो DoPollingThenWork। यह पाठकों के लिए भ्रम को कम करेगा।


धन्यवाद, लेकिन कृपया मुझे बताएं कि क्या होता है जब हम थ्रेड की कोई संख्या नहीं कहते हैं 10. जब 10 में से एक थ्रेड फिनिश खत्म हो जाए तो फिर से थ्रेड कूदने पर दूसरी नौकरी खत्म हो जाती है या पूल में वापस चली जाती है? यह बहुत स्पष्ट नहीं है .... इसलिए कृपया समझाएं कि दृश्य के पीछे क्या होता है।
एमओ

@ क्या इसके बारे में स्पष्ट नहीं है? जब तक वर्तमान में चल रहे 10 से कम कार्य नहीं होते तब तक कोड प्रतीक्षा करता है; जब होते हैं, यह एक और जोड़ता है। जब कोई कार्य समाप्त होता है तो यह इंगित करता है कि यह समाप्त हो गया है। बस।
21

थ्रेड को न चलाने के लिए निर्दिष्ट करने का क्या फायदा है। अगर बहुत सारे धागे प्रदर्शन में बाधा डाल सकते हैं? यदि हाँ तो बाधा क्यों ... यदि मैं 10 धागे के बजाय 50 धागे चलाता हूं तो प्रदर्शन क्यों मायने रखेगा ... क्या आप कृपया समझा सकते हैं। धन्यवाद
थॉमस

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

3
@ सेरी यह कार्य शेड्यूलर की नौकरी का हिस्सा है। कार्य! = धागे। Thread.Sleepमूल कोड में कार्य अनुसूचक उजाड़ना होगा। यदि आप कोर के लिए async नहीं हैं, तो आप async नहीं हैं।
जोसेफ लेनोक्स

67

पीई कमरे में कितने बच्चे खेल सकते हैं, यह नियंत्रित करने के लिए कोने के चारों ओर किंडरगार्डन में वे सेमफोरस्लीम का उपयोग करते हैं।

उन्होंने फर्श पर, कमरे के बाहर, 5 जोड़ी पैरों के निशान चित्रित किए।

जैसे ही बच्चे आते हैं, वे अपने जूते को पैरों के निशान से मुक्त करते हैं और कमरे में प्रवेश करते हैं।

एक बार जब वे खेल कर जाते हैं तो वे बाहर आते हैं, अपने जूते इकट्ठा करते हैं और दूसरे बच्चे के लिए एक स्लॉट "जारी" करते हैं।

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

जब एक शिक्षक आसपास होता है, तो वह गलियारे के दूसरी तरफ 5 पैरों के निशान की एक अतिरिक्त पंक्ति "जारी" करता है, ताकि एक ही समय में 5 और बच्चे कमरे में खेल सकें।

यह भी SemaphoreSlim के "नुकसान" एक ही है ...

यदि कोई बच्चा खेल खत्म कर देता है और जूते इकट्ठा किए बिना कमरा छोड़ देता है ("रिलीज" को ट्रिगर नहीं करता है) तो स्लॉट अवरुद्ध रहता है, भले ही सैद्धांतिक रूप से एक खाली स्लॉट हो। बच्चा आमतौर पर बंद हो जाता है, हालांकि।

कभी-कभी एक या दो डरपोक बच्चे अपने जूते कहीं और छिपाते हैं और कमरे में प्रवेश करते हैं, भले ही सभी पैरों के निशान पहले से ही ले लिए गए हों (यानी, सेमफोरस्लीम "वास्तव में" को नियंत्रित नहीं करता है कि कमरे में कितने बच्चे हैं)।

यह आमतौर पर अच्छी तरह से समाप्त नहीं होता है, क्योंकि कमरे की अधिक भीड़ बच्चों के रोने में समाप्त हो जाती है और शिक्षक पूरी तरह से कमरे को बंद कर देता है।


9
इस प्रकार के उत्तर मेरे पसंदीदा हैं।
मेरा स्टैक

7

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

http://www.tomdupont.net/2016/03/how-to-release-semaphore-with-using.html

मैंने स्वैप किया _isDisposed=trueऔर _semaphore.Release()इसके डिस्पोज़ में इधर - उधर किया, हालाँकि किसी तरह इसे कई बार कॉल किया गया।

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

प्रश्न कोड-गुणवत्ता के संबंध में, रिलीज को अंततः एक कोशिश के अंत में रखना बेहतर होता है ताकि यह सुनिश्चित हो सके कि यह हमेशा जारी हो।


6
यह लिंक-केवल उत्तर पोस्ट करने के लिए अनुपयुक्त है क्योंकि लिंक समय के साथ मर जाते हैं और इस प्रकार उत्तर को बेकार कर देते हैं। यदि आप कर सकते हैं, तो आपके उत्तर में मुख्य बिंदुओं या प्रमुख कोड ब्लॉक को संक्षेप में प्रस्तुत करना सबसे अच्छा है।
जॉन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.