ताला, म्यूटेक्स, सेमाफोर ... क्या अंतर है?


439

मैंने समवर्ती प्रोग्रामिंग से संबंधित इन शब्दों को सुना है, लेकिन उनके बीच क्या अंतर है?



2
सबसे अच्छी व्याख्या जो मैंने कभी देखी है: क्रिस्टल.टू.ड्यू
सीसी

जवाबों:


534

एक लॉक केवल एक धागे को उस हिस्से में प्रवेश करने की अनुमति देता है जो लॉक है और किसी अन्य प्रक्रिया के साथ लॉक साझा नहीं किया गया है।

एक म्यूटेक्स एक लॉक के समान है लेकिन यह सिस्टम वाइड (कई प्रक्रियाओं द्वारा साझा) हो सकता है।

एक सेमाफोर एक म्यूटेक्स के रूप में एक ही करता है लेकिन एक्स के थ्रेड की संख्या को दर्ज करने की अनुमति देता है, इसका उपयोग उदाहरण के लिए सीपीयू, आईओ या रैम गहन कार्यों को एक ही समय में सीमित करने के लिए किया जा सकता है।

म्यूटेक्स और सेमाफोर के बीच अंतर के बारे में अधिक विस्तृत पोस्ट के लिए यहां पढ़ें ।

आपने ऐसे लॉक / रीड भी पढ़े हैं जो किसी भी समय असीमित संख्या में पाठकों या 1 लेखक की अनुमति देता है।


2
@mertinan मैं यह नहीं कह सकता कि मैंने इसके बारे में कभी सुना है, लेकिन यह वही विकिपीडिया है जो "Latch (डेटाबेस), (एक अपेक्षाकृत अल्पकालिक) एक इंडेक्स की तरह सिस्टम डेटा-स्ट्रक्चर पर लॉक करता है"
पीटर

2
मॉनिटर एक निश्चित स्थिति के लिए प्रतीक्षा करने की अनुमति देता है (उदाहरण के लिए जब लॉक जारी होता है), "मॉनिटर"।
Dzmitry Lazerka

25
एक अर्धकुंभ म्यूटेक्स के समान नहीं है। उनका उपयोग बहुत अलग तरीके से किया जाता है और अलग-अलग गुण भी होते हैं (अर्थात् स्वामित्व के संबंध में)। उदाहरण के लिए देखें barrgroup.com/Embedded-Systems/How-To/RTOS-Mutex-Semaphore for details
nanoquack

3
@nanoquack मेरे उत्तर को संपादित करने के लिए स्वतंत्र महसूस करें यदि आपको लगता है कि यह भ्रामक या गलत है।
पीटर

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

117

इन शब्दों के बारे में बहुत सारी गलत धारणाएँ हैं।

यह एक पिछली पोस्ट ( https://stackoverflow.com/a/24582076/3163691 ) से है जो यहाँ बहुत ही शानदार है:

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

[नो इंटरप्रोसेस क्षमता, बहुत आदिम वस्तु]।

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

[Interprocess क्षमता, उपयोग करने के लिए बहुत सुरक्षित, एक प्रकार का 'उच्च स्तर' तुल्यकालन वस्तु]।

3) गणना सेमाफोर (उर्फ सेमाफोर) = कर्नेल ऑब्जेक्ट का उपयोग कई अन्य लोगों के सक्रिय थ्रेड के एक समूह के निष्पादन के लिए किया जाता है। अन्य गैर चयनित थ्रेड्स (@ इस ऑब्जेक्ट को प्राप्त करना) को सोने के लिए रखा जाता है ।

[अंतरप्रणाली क्षमता हालांकि उपयोग करने के लिए बहुत सुरक्षित नहीं है क्योंकि इसमें 'म्यूटेक्स' विशेषताओं का अभाव है: थ्रेड टर्मिनेशन अधिसूचना, पुनरावृत्ति ;, 'प्राथमिकता व्युत्क्रमण परिहार'? आदि]।

4) और अब, 'स्पिनलॉक' के बारे में बात कर रहे हैं, पहले कुछ परिभाषाएँ:

महत्वपूर्ण क्षेत्र = 2 या अधिक प्रक्रियाओं द्वारा साझा की गई स्मृति का क्षेत्र।

लॉक = एक वैरिएबल जिसका मान किसी 'महत्वपूर्ण क्षेत्र' के प्रवेश द्वार को अनुमति देता है या मना करता है। (इसे एक साधारण 'बुलियन फ्लैग' के रूप में लागू किया जा सकता है)।

व्यस्त प्रतीक्षा = किसी मान के प्रकट होने तक किसी चर का निरंतर परीक्षण।

आखिरकार:

स्पिन-लॉक (उर्फ स्पिनलॉक) = एक लॉक जो व्यस्त प्रतीक्षा का उपयोग करता है । ( लॉक का अधिग्रहण xchg या इसी तरह के परमाणु परिचालनों द्वारा किया जाता है )।

[कोई धागा नहीं सो रहा है, ज्यादातर केवल कर्नेल स्तर पर उपयोग किया जाता है। उपयोगकर्ता स्तर कोड के लिए अप्रभावी]।

अंतिम टिप्पणी के रूप में, मुझे यकीन नहीं है लेकिन मैं आपको कुछ बड़े रुपये दे सकता हूं जो उपरोक्त पहले 3 सिंक्रनाइज़ेशन ऑब्जेक्ट्स (# 1, # 2 और # 3) उनके कार्यान्वयन के हिस्से के रूप में इस सरल जानवर (# 4) का उपयोग करते हैं।

आपका दिन शुभ हो!।

संदर्भ:

-रेल-टाइम कॉन्सेप्ट सिस्टम फॉर एंबेडेड सिस्टम फॉर किंग ली विद कैरोलिन याओ (सीएमपी बुक्स)।

एंड्रयू टेनबाम (पियर्सन एजुकेशन इंटरनेशनल) द्वारा -Modern ऑपरेटिंग सिस्टम (3 जी)।

जेफ़री रिक्टर (Microsoft प्रोग्रामिंग सीरीज़) द्वारा माइक्रोसॉफ्ट विंडोज (4 वें) के लिए -प्रोग्रामिंग एप्लीकेशन।

इसके अलावा, आप एक नज़र देख सकते हैं: https://stackoverflow.com/a/24586803/3163691


1
वास्तव में क्रिटिकल सेक्शन एक कर्नेल ऑब्जेक्ट नहीं है, इस प्रकार यह अधिक हल्का और पूरी प्रक्रियाओं में सिंक्रोनाइज़ करने में असमर्थ है।
व्लादिस्लाव्स बुरकोव्स

2
@ व्लादिस्लाव बर्कोव्स: आप सही कह रहे हैं! मेरे लाल को माफ़ कर दो। मैं इसे सुसंगतता के लिए ठीक करूँगा।
काल्पनिक

म्यूटेक्स और सेमाफोर के बीच स्पष्ट अंतर के लिए, जैसा कि नैनोक्वाक कहीं और उल्लेख करता है, देखें barrgroup.com/Embedded-Systems/How-To/RTOS-Mutex-Sadfore - मुख्य पैराग्राफ " एक काम से सिग्नलिंग के लिए एक सेमाफोर का सही उपयोग है" दूसरे के लिए। एक म्यूटेक्स का अर्थ होता है लिया और जारी किया जाना, हमेशा उस क्रम में, प्रत्येक कार्य द्वारा जो साझा किए गए संसाधन का उपयोग करता है, वह इसकी रक्षा करता है। इसके विपरीत, ऐसे कार्य जो सेमाफोर या तो सिग्नल का उपयोग करते हैं या दोनों का इंतजार नहीं करते हैं। "
टूलमेकरसेवेट

[अकुशल] स्पिनलॉक पर निर्मित अन्य लॉक मैकेनिज्म को पुन: अनुमानित करना: संभावना नहीं है; AFAIK को केवल कुछ परमाणु परिचालनों और नींद की कतारों की आवश्यकता है। यहां तक ​​कि जहां कर्नेल के अंदर स्पिनकॉक की आवश्यकता होती है, आधुनिक समाधान विकिपीडिया में वर्णित के रूप में इसके प्रभाव को कम करते हैं - स्पिनलॉक - विकल्प - " .. " एडेप्टिव म्यूटेक्स "नामक हाइब्रिड दृष्टिकोण का उपयोग करें। विचार एक लॉकलॉक का उपयोग करने के लिए होता है जब किसी संसाधन को लॉक करने की कोशिश की जाती है। एक वर्तमान में चल रहा धागा, लेकिन यदि धागा वर्तमान में नहीं चल रहा है तो सोने के लिए। (उत्तरार्द्ध हमेशा एकल-प्रोसेसर सिस्टम पर मामला होता है।) "
टूलमेकरसैट

@ टोलमेकरसेव, मैंने आपको 'नींद' के लिए एक थ्रेड आईडी 'थ्रेड' डालने की कोशिश में 'टकराव' की समस्या के लिए एक 'समाधान' के बिना एक 'समाधान' प्रदान करने की हिम्मत की। वैसे भी, विकिपीडिया पाठ यह निष्कर्ष निकालता है कि कार्यान्वयन में एक स्पिनलॉक का उपयोग किया जाता है !!!।
फंतासी

27

अधिकांश समस्याओं को (i) सिर्फ ताले का उपयोग करके हल किया जा सकता है, (ii) सिर्फ semaphores, ..., या (iii) दोनों का संयोजन! जैसा कि आपने खोजा होगा, वे बहुत ही समान हैं: दोनों ही दौड़ की स्थिति को रोकते हैं , दोनों के पास acquire()/ release()ऑपरेशन हैं, दोनों शून्य या अधिक थ्रेड्स अवरुद्ध / संदिग्ध होने का कारण बनते हैं ... वास्तव में, महत्वपूर्ण अंतर केवल इस बात पर निहित है कि वे कैसे लॉक और अनलॉक करते हैं

  • एक लॉक (या म्यूटेक्स ) में दो राज्य (0 या 1) हैं। इसे या तो अनलॉक या लॉक किया जा सकता है । उनका उपयोग अक्सर यह सुनिश्चित करने के लिए किया जाता है कि एक समय में केवल एक धागा एक महत्वपूर्ण खंड में प्रवेश करता है।
  • एक सेमाफोर में कई राज्य होते हैं (0, 1, 2, ...)। इसे लॉक (राज्य 0) या अनलॉक किया जा सकता है (राज्य 1, 2, 3, ...)। एक या अधिक सेमाफोर का उपयोग अक्सर यह सुनिश्चित करने के लिए किया जाता है कि केवल एक धागा एक महत्वपूर्ण खंड में ठीक से प्रवेश करता है, जब किसी संसाधन की इकाइयों की संख्या एक विशेष मूल्य तक नहीं पहुंची है (या तो उस मूल्य तक की गिनती के माध्यम से या उस मूल्य तक गिनती के माध्यम से) )।

दोनों तालों / सेमाफोर के लिए, कॉल करने की कोशिश acquire()करते समय, आदिम अवस्था में है 0 इनवॉइस थ्रेड को निलंबित करने का कारण बनता है। ताले के लिए - ताला प्राप्त करने का प्रयास राज्य में है 1 सफल हैं। सेमाफोरेस के लिए - राज्यों में ताला प्राप्त करने का प्रयास {1, 2, 3, ...} सफल हैं।

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

पूर्ववर्ती चर्चा से, हम देख सकते हैं कि ताले में एक मालिक की धारणा है (एकमात्र धागा जिसे रिलीज़ जारी कर सकते हैं, वह मालिक है), जबकि सेमीफ़ोर्स में कोई स्वामी नहीं है (कोई भी धागा एक सेमीफ़ोर पर रिलीज़ कॉल कर सकता है)।


बहुत सारे भ्रम का कारण बनता है, व्यवहार में, वे इस उच्च-स्तरीय परिभाषा के कई रूप हैं ।

विचार करने के लिए महत्वपूर्ण विविधताएं :

  • acquire()/ क्या release()कहा जाना चाहिए ? - [ बड़े पैमाने पर बदलता है ]
  • क्या आपके लॉक / सेमाफोर धागे का इंतजार करने के लिए "कतार" या "सेट" का उपयोग करते हैं?
  • क्या आपके लॉक / सेमाफोर को अन्य प्रक्रियाओं के धागे के साथ साझा किया जा सकता है?
  • क्या आपका ताला "रेस्ट्रेंट" है? - [आमतौर पर हाँ]।
  • क्या आपका लॉक "ब्लॉकिंग / नॉन-ब्लॉकिंग" है? - "सामान्य रूप से गैर-अवरोधक का उपयोग अवरुद्ध ताले (उर्फ स्पिन-ताले) के रूप में किया जाता है जो व्यस्त प्रतीक्षा का कारण बनता है]।
  • आप कैसे सुनिश्चित करते हैं कि ऑपरेशन "परमाणु" हैं?

ये आपकी पुस्तक / व्याख्याता / भाषा / पुस्तकालय / पर्यावरण पर निर्भर करता है।
यहाँ एक त्वरित दौरा दिखाया गया है कि कैसे कुछ भाषाएं इन विवरणों का उत्तर देती हैं।


सी, सी ++ ( pthreads )

  • एक म्यूटेक्स के माध्यम से कार्यान्वित किया जाता है pthread_mutex_t। डिफ़ॉल्ट रूप से, उन्हें किसी भी अन्य प्रक्रियाओं ( PTHREAD_PROCESS_PRIVATE) के साथ साझा नहीं किया जा सकता है , हालांकि म्यूटेक्स की विशेषता एक विशेषता है जिसे Psared कहा जाता है । जब सेट किया जाता है, तो म्यूटेक्स को प्रक्रियाओं ( PTHREAD_PROCESS_SHARED) के बीच साझा किया जाता है ।
  • एक ताला म्यूटेक्स के समान है।
  • एक सेमाफोर के माध्यम से कार्यान्वित किया जाता है sem_t। म्यूटेक्स के समान, कई प्रक्रियाओं के थ्रेड्स के बीच सेमाफोर को साझा किया जा सकता है या एक एकल प्रक्रिया के थ्रेड्स के लिए निजी रखा जा सकता है। यह उपलब्ध कराए गए मानदंड तर्क पर निर्भर करता है sem_init

अजगर ( सूत्रण )

  • एक ताला ( threading.RLock) ज्यादातर C / C ++ pthread_mutex_ts के समान है। दोनों ही प्रतिवादी हैं । इसका मतलब है कि वे केवल उसी धागे से अनलॉक हो सकते हैं जिसने इसे लॉक किया था। यह मामला है कि sem_tसेमाफोरस, threading.Semaphoreसेमाफोर और theading.Lockलॉक्स रेफरेंट नहीं हैं - इसके लिए यह है कि कोई भी धागा सेमाफोर को लॉक / डाउन अनलॉक कर सकता है।
  • एक म्यूटेक्स लॉक के समान है (शब्द का उपयोग अक्सर अजगर में नहीं किया जाता है)।
  • एक सेमाफोर ( threading.Semaphore) ज्यादातर के समान है sem_t। यद्यपि इसके साथ sem_t, थ्रेड आईडी की एक कतार का उपयोग उस क्रम को याद रखने के लिए किया जाता है जिसमें थ्रेड्स लॉक होने का प्रयास करते समय अवरुद्ध हो जाते हैं। जब एक धागा एक सेमाफोर को अनलॉक करता है, तो कतार में पहला धागा (यदि एक है) को नया मालिक चुना जाता है। थ्रेड आइडेंटिफायर को कतार से बाहर ले जाया जाता है और सेमीफोर फिर से लॉक हो जाता है। हालांकि, के साथ threading.Semaphore, एक कतार के बजाय एक सेट का उपयोग किया जाता है, इसलिए जिस क्रम में धागे अवरुद्ध हो गए हैं वह संग्रहीत नहीं किया जाता है - सेट में किसी भी धागे को अगले मालिक के लिए चुना जा सकता है।

जावा ( java.util.concurrent )

  • एक ताला ( java.util.concurrent.ReentrantLock) ज्यादातर C / C ++ के समान ही होता है pthread_mutex_t, और Python's इस रूप threading.RLockमें भी है कि यह एक लॉक लॉक को भी लागू करता है। JVM के मध्यस्थ के रूप में कार्य करने के कारण प्रक्रियाओं के बीच ताले साझा करना जावा में कठिन है। यदि कोई थ्रेड लॉक को अनलॉक करने का प्रयास करता है तो वह स्वयं नहीं है, एक IllegalMonitorStateExceptionफेंका गया है।
  • एक म्यूटेक्स एक लॉक के समान है (जावा में शब्द का अक्सर उपयोग नहीं किया जाता है)।
  • एक सेमाफोर ( java.util.concurrent.Semaphore) ज्यादातर रूप में ही है sem_tऔर threading.Semaphore। जावा सेमाफोर के लिए निर्माता एक निष्पक्षता को स्वीकार करते हैं बूलियन पैरामीटर को जो प्रतीक्षा थ्रेड्स के भंडारण के लिए एक सेट (गलत) या एक कतार (सच) का उपयोग करने के लिए नियंत्रित करता है।

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


22

जॉन कोपलिन द्वारा मल्टीथ्रेडिंग ट्यूटोरियल पर एक नज़र डालें।

थ्रेड्स के बीच सेक्शन सिंक्रोनाइज़ेशन में , वह ईवेंट, लॉक, म्यूटेक्स, सेमाफोर, वेटरटेबल टाइमर के बीच अंतरों की व्याख्या करता है

एक म्यूटेक्स को एक समय में केवल एक धागे के स्वामित्व में रखा जा सकता है, जिससे धागे साझा संसाधन के लिए पारस्परिक रूप से अनन्य पहुंच को समन्वयित कर सकते हैं

गंभीर खंड वस्तुओं म्यूटेक्स ऑब्जेक्ट्स द्वारा प्रदान किए गए समान तुल्यकालन प्रदान करते हैं, सिवाय इसके कि महत्वपूर्ण सेक्शन ऑब्जेक्ट्स को केवल एक प्रक्रिया के थ्रेड्स द्वारा उपयोग किया जा सकता है

म्यूटेक्स और एक महत्वपूर्ण खंड के बीच एक और अंतर यह है कि यदि महत्वपूर्ण खंड ऑब्जेक्ट वर्तमान में किसी अन्य थ्रेड EnterCriticalSection()के स्वामित्व में है, तो स्वामित्व के दौरान अनिश्चित काल तक प्रतीक्षा करता है WaitForSingleObject() , तो , एक म्यूटेक्स के साथ उपयोग किया जाता है, जो आपको एक टाइमआउट निर्दिष्ट करने की अनुमति देता है

एक सेमाफोर शून्य और कुछ अधिकतम मूल्य के बीच एक गिनती रखता है, एक साथ एक साझा संसाधन तक पहुंचने वाले थ्रेड्स की संख्या को सीमित करता है।


15

मैं इसे उदाहरणों के साथ कवर करने का प्रयास करूंगा:

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

private static readonly Object obj = new Object();

lock (obj) //after object is locked no thread can come in and insert item into dictionary on a different thread right before other thread passed the check...
{
    if (!sharedDict.ContainsKey(key))
    {
        sharedDict.Add(item);
    }
}

सेमाफोर: मान लीजिए कि आपके पास कनेक्शन का एक पूल है, तो एक एकल धागा कनेक्शन प्राप्त करने के लिए सेमीफोर का इंतजार करके पूल में एक तत्व को आरक्षित कर सकता है। यह तब कनेक्शन का उपयोग करता है और जब काम पूरा हो जाता है तो कनेक्शन को सेमाफोर जारी करके जारी करता है।

कोड उदाहरण है कि मैं प्यार करता हूँ @Patric द्वारा दिए गए बाउंसर में से एक है - यहाँ यह जाता है:

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace TheNightclub
{
    public class Program
    {
        public static Semaphore Bouncer { get; set; }

        public static void Main(string[] args)
        {
            // Create the semaphore with 3 slots, where 3 are available.
            Bouncer = new Semaphore(3, 3);

            // Open the nightclub.
            OpenNightclub();
        }

        public static void OpenNightclub()
        {
            for (int i = 1; i <= 50; i++)
            {
                // Let each guest enter on an own thread.
                Thread thread = new Thread(new ParameterizedThreadStart(Guest));
                thread.Start(i);
            }
        }

        public static void Guest(object args)
        {
            // Wait to enter the nightclub (a semaphore to be released).
            Console.WriteLine("Guest {0} is waiting to entering nightclub.", args);
            Bouncer.WaitOne();          

            // Do some dancing.
            Console.WriteLine("Guest {0} is doing some dancing.", args);
            Thread.Sleep(500);

            // Let one guest out (release one semaphore).
            Console.WriteLine("Guest {0} is leaving the nightclub.", args);
            Bouncer.Release(1);
        }
    }
}

Mutex यह बहुत अधिक है Semaphore(1,1)और अक्सर विश्व स्तर पर उपयोग किया जाता है (व्यापक रूप lockसे व्यापक अन्यथा यकीनन अधिक उपयुक्त है)। एक वैश्विक रूप Mutexसे सुलभ सूची से नोड को हटाते समय एक वैश्विक उपयोग करेगा (आखिरी चीज जब आप नोड को हटा रहे हैं तो कुछ और करना चाहते हैं)। जब आप Mutexअलग-अलग थ्रेड प्राप्त करते हैं, तो Mutexइसे प्राप्त करने की कोशिश करता है, तो इसे एसएएमई थ्रेड तक सोने के लिए रखा जाएगा जो Mutexइसे रिलीज करता है।

वैश्विक म्यूटेक्स बनाने पर अच्छा उदाहरण @deepee द्वारा है

class SingleGlobalInstance : IDisposable
{
    public bool hasHandle = false;
    Mutex mutex;

    private void InitMutex()
    {
        string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString();
        string mutexId = string.Format("Global\\{{{0}}}", appGuid);
        mutex = new Mutex(false, mutexId);

        var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow);
        var securitySettings = new MutexSecurity();
        securitySettings.AddAccessRule(allowEveryoneRule);
        mutex.SetAccessControl(securitySettings);
    }

    public SingleGlobalInstance(int timeOut)
    {
        InitMutex();
        try
        {
            if(timeOut < 0)
                hasHandle = mutex.WaitOne(Timeout.Infinite, false);
            else
                hasHandle = mutex.WaitOne(timeOut, false);

            if (hasHandle == false)
                throw new TimeoutException("Timeout waiting for exclusive access on SingleInstance");
        }
        catch (AbandonedMutexException)
        {
            hasHandle = true;
        }
    }


    public void Dispose()
    {
        if (mutex != null)
        {
            if (hasHandle)
                mutex.ReleaseMutex();
            mutex.Dispose();
        }
    }
}

तो उपयोग की तरह:

using (new SingleGlobalInstance(1000)) //1000ms timeout on global lock
{
    //Only 1 of these runs at a time
    GlobalNodeList.Remove(node)
}

आशा है कि यह आपको कुछ समय बचाता है।


8

सेमाफोरस और म्यूटेक्स के बीच अंतर पर विकिपीडिया का एक बड़ा वर्ग है :

एक म्यूटेक्स अनिवार्य रूप से एक बाइनरी सेमाफोर के समान है और कभी-कभी एक ही मूल कार्यान्वयन का उपयोग करता है। उनके बीच अंतर हैं:

म्यूटेक्स में एक मालिक की अवधारणा है, जो कि म्यूटेक्स को बंद करने वाली प्रक्रिया है। केवल म्यूटेक्स को लॉक करने वाली प्रक्रिया ही इसे अनलॉक कर सकती है। इसके विपरीत, एक सेमाफोर में मालिक की कोई अवधारणा नहीं होती है। कोई भी प्रक्रिया एक सेमाफोर को अनलॉक कर सकती है।

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

म्यूटेक्स भी विलोपन सुरक्षा प्रदान करता है, जहां म्यूटेक्स को पकड़े जाने की प्रक्रिया को गलती से हटाया नहीं जा सकता है। सेमाफोर इसे प्रदान नहीं करते हैं।


5

मेरी समझ यह है कि एक म्यूटेक्स केवल एक प्रक्रिया के भीतर उपयोग के लिए है, लेकिन इसके कई थ्रेड्स में, जबकि एक सेमाफोर का उपयोग कई प्रक्रियाओं में किया जा सकता है, और उनके संबंधित थ्रेड्स के सेट पर।

इसके अलावा, एक म्यूटेक्स बाइनरी है (यह या तो लॉक या अनलॉक किया गया है), जबकि एक सेमाफोर में गिनती की धारणा है, या एक से अधिक लॉक और अनलॉक अनुरोधों की कतार है।

क्या कोई मेरे स्पष्टीकरण को सत्यापित कर सकता है? मैं लिनक्स के संदर्भ में बोल रहा हूं, विशेष रूप से Red Hat Enterprise Linux (RHEL) संस्करण 6, जो कर्नेल 2.6.32 का उपयोग करता है।


3
अब यह अलग-अलग ऑपरेटिंग सिस्टम में भिन्न हो सकता है, लेकिन विंडोज़ में एक म्यूटेक्स का उपयोग कई प्रक्रियाओं द्वारा कम से कम .net म्यूटेक्स ऑब्जेक्ट में किया जा सकता है ..
पीटर

2
stackoverflow.com/questions/9389730/… "एक ही प्रक्रिया के भीतर या अन्य प्रक्रियाओं के भीतर थूक मूक साझा कर सकते हैं।" इसलिए कोई म्यूटेक्स प्रक्रिया विशेष नहीं होनी चाहिए।
पीटर

3

उदाहरण के लिए बेस केस के रूप में लिनक्स वेरिएंट पर C प्रोग्रामिंग का उपयोग करना।

लॉक करें:

• आमतौर पर एक बहुत ही सरल निर्माण बाइनरी ऑपरेशन में या तो लॉक या अनलॉक किया गया

• धागा स्वामित्व, प्राथमिकता, अनुक्रमण आदि की कोई अवधारणा नहीं।

• आमतौर पर एक स्पिन लॉक जहां थ्रेड लगातार तालों की उपलब्धता की जांच करता है।

• आमतौर पर परमाणु परिचालनों पर निर्भर करता है जैसे टेस्ट-एंड-सेट, तुलना-और-स्वैप, भ्रूण और जोड़ आदि।

• आमतौर पर परमाणु संचालन के लिए हार्डवेयर समर्थन की आवश्यकता होती है।

फ़ाइल ताले:

• आमतौर पर कई प्रक्रियाओं के माध्यम से एक फ़ाइल तक पहुंच को समन्वयित करने के लिए उपयोग किया जाता है।

• एकाधिक प्रक्रियाएं रीड लॉक को पकड़ सकती हैं, जब कोई एकल प्रक्रिया राइट लॉक रखती है तो किसी अन्य प्रक्रिया को रीड या राइट लॉक प्राप्त करने की अनुमति नहीं है।

• उदाहरण: झुंड, fcntl आदि।

म्युटेक्स:

• म्यूटेक्स फ़ंक्शन कॉल आमतौर पर कर्नेल स्थान और सिस्टम कॉल में काम करते हैं।

• यह स्वामित्व की अवधारणा का उपयोग करता है। केवल थ्रेड जो वर्तमान में म्यूटेक्स रखता है, उसे अनलॉक कर सकता है।

• म्यूटेक्स पुनरावर्ती नहीं है (अपवाद: PTHREAD_MUTEX_RECURSIVE)।

• आमतौर पर हालत चर के साथ एसोसिएशन में इस्तेमाल किया और उदाहरण के लिए तर्कों के रूप में पारित किया pthread_cond_signal, pthread_cond_wait आदि।

• कुछ यूनिक्स सिस्टम म्यूटेक्स को कई प्रक्रियाओं द्वारा उपयोग करने की अनुमति देते हैं, हालांकि यह सभी प्रणालियों पर लागू नहीं किया जा सकता है।

सेमाफोर:

• यह एक कर्नेल अनुरक्षित पूर्णांक है जिसका मान शून्य से नीचे गिरने की अनुमति नहीं है।

• इसका उपयोग प्रक्रियाओं को सिंक्रनाइज़ करने के लिए किया जा सकता है।

• सेमाफोर का मान 1 से अधिक मूल्य पर सेट किया जा सकता है, जिस स्थिति में मूल्य आमतौर पर उपलब्ध संसाधनों की संख्या को इंगित करता है।

• एक सेमाफोर जिसका मान 1 और 0 तक सीमित है, को बाइनरी सेमाफोर कहा जाता है।


0

Supporting ownership, maximum number of processes share lock और maximum number of allowed processes/threads in critical sectionतीन प्रमुख कारक हैं जो सामान्य नाम के साथ समवर्ती वस्तु का नाम / प्रकार निर्धारित करते हैं lock। चूंकि इन कारकों का मूल्य द्विआधारी है (दो राज्य हैं), हम उन्हें 3 * 8 सच्चाई जैसी तालिका में सारांशित कर सकते हैं।

  • X (स्वामित्व का समर्थन करता है?): नहीं (0) / हाँ (1)
  • Y (# प्रक्रियाएँ):> 1 (/) / 1
  • जेड (# सीए में प्रक्रिया / सूत्र):> 1 (/) / 1

  X   Y   Z          Name
 --- --- --- ------------------------
  0   ∞   ∞   Semaphore              
  0   ∞   1   Binary Semaphore       
  0   1   ∞   SemaphoreSlim          
  0   1   1   Binary SemaphoreSlim(?)
  1   ∞   ∞   Recursive-Mutex(?)     
  1   ∞   1   Mutex                  
  1   1   ∞   N/A(?)                 
  1   1   1   Lock/Monitor           

इस तालिका को संपादित करने या विस्तार करने के लिए स्वतंत्र महसूस करें, मैंने इसे संपादन योग्य होने के लिए एक आस्की टेबल के रूप में पोस्ट किया है :)

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