2009-09-28 11 views
42

कुछ कार्यान्वयन विशिष्ट अनुप्रयोगों के लिए दूसरों की तुलना में बेहतर हैं? क्या अपना खुद का रोलिंग करके कमाई करने के लिए कुछ भी है?म्यूटेक्स कैसे कार्यान्वित किए जाते हैं?

+7

"क्या अपना खुद का रोलिंग करके कमाई करने के लिए कुछ भी है?" ज्ञान? –

+14

"क्या अपना खुद का रोलिंग करके कमाई करने के लिए कुछ भी है?" - हाँ, दोषपूर्ण कोड! ;) –

+5

@ मिच गेहूं - निश्चित रूप से, किसी को उत्पादन कोड के लिए होमब्रू म्यूटेक्स पुस्तकालयों का उपयोग नहीं करना चाहिए, लेकिन बहुत से लोग ऐसा करके सीखना पसंद करते हैं, और अपना खुद का [आवेदन x] लिखना बहुत ही जानकारीपूर्ण है। –

उत्तर

21

विकिपीडिया पर Test-and-set मशीन निर्देश का विवरण देखें, जो बताता है कि मशीन स्तर पर परमाणु संचालन कैसे प्राप्त किए जाते हैं। मैं कल्पना कर सकता हूं कि अधिकांश भाषा-स्तर म्यूटेक्स कार्यान्वयन मशीन-स्तरीय समर्थन जैसे टेस्ट-एंड-सेट पर भरोसा करते हैं।

+0

उदाहरण के लिए x86 पर, आप स्मृति के साथ एक रजिस्टर को स्वैच्छिक रूप से स्वैप करने के लिए 'xchg' निर्देश का उपयोग कर सकते हैं। स्टोर भाग "सेट" है, और रजिस्टर भाग पर लोड भाग + शाखाकरण परीक्षण-और-सेट ऑपरेशन का "परीक्षण" आधा है। और हां, यह अभ्यास में आप जो भी करते हैं उतना ही कम है। [एएसएम में यह न्यूनतम स्पिनलॉक कार्यान्वयन] देखें [https://stackoverflow.com/questions/37241553/locks-around-memory-manipulation-via-inline-assembly/37246263#37246263) जो पीछे की ओर छोड़कर अधिकांश महत्वपूर्ण चीजें करता है लॉक प्राप्त किए बिना थोड़ी देर के लिए कताई के बाद सिस्टम कॉल में सोना। –

2

Interlocked.CompareExchange स्पिनलॉक्स को लागू करने के लिए पर्याप्त है। यद्यपि सही करना मुश्किल है। शामिल subtleties के उदाहरण के लिए Joe Duffy's blog के लिए देखें।

+0

हम यहां भाषा-अज्ञेय समाधानों के बारे में बात कर रहे हैं, लेकिन आपके प्रयास के लिए धन्यवाद। –

+0

ओह, आप सही हैं। मुझे नहीं पता कि मैं क्यों सोच रहा था .NET। शायद अन्य उत्तरों के कारण। – Joren

6

mutex अधिमानतः ऑपरेटिंग सिस्टम के कर्नेल में चलता है जबकि इसे जितना संभव हो सके कोड की मात्रा को रखते हुए, इसलिए यह किसी अन्य प्रक्रिया में कार्य-स्विचिंग के दौरान कट ऑफ होने से बच सकता है। सटीक कार्यान्वयन इसलिए एक रहस्य का थोड़ा सा है। हालांकि यह जटिल नहीं है। यह मूल रूप से एक वस्तु है जिसमें एक बूलियन क्षेत्र होता है, जो इसे प्राप्त करता है और सेट करता है।

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

मूल म्यूटेक्स तर्क के आसपास रैपर को किसी ऑब्जेक्ट में लपेटने के लिए हैं .. फिर अधिक रैपर ऑब्जेक्ट्स इसे कर्नेल के बाहर उपलब्ध कराने के लिए। और फिर एक और रैपर इसे .NET में उपलब्ध कराने के लिए। और फिर कई प्रोग्रामर अपनी खुद की तार्किक जरूरतों के लिए अपने स्वयं के रैपर कोड लिखेंगे। रैपर के चारों ओर रैपर वास्तव में उन्हें एक गन्दा क्षेत्र बनाते हैं।

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

जहां तक ​​मुझे पता है, विंडोज, लिनक्स और .NET सभी कर्नेल/हार्डवेयर स्तर पर म्यूटेक्स का उपयोग करेंगे।

विकिपीडिया पेज जो मैंने लिंक किया है, आंतरिक तर्क और संभावित कार्यान्वयन के बारे में और बताता है। अधिमानतः, एक म्यूटेक्स हार्डवेयर द्वारा नियंत्रित होता है, इस प्रकार म्यूटेक्स को indivisible step की पूरी हो रही/सेटिंग कर रहा है। (बस यह सुनिश्चित करने के लिए कि सिस्टम कार्यों के बीच में स्विच नहीं करता है।)

+0

+1। अच्छा उत्तर। –

+0

आपका क्या मतलब है कि यह एक रहस्य है? गिटहब में उपलब्ध संपूर्ण लिनक्स कर्नेल स्रोत कोड नहीं है? –

+0

ओह, गीज़। 8 साल पहले जब मैंने लिखा था! :) लेकिन हाँ, यह एक रहस्य है क्योंकि कोई भी वास्तव में लिनक्स कर्नेल में म्यूटेक्स के लिए स्रोत कोड की जांच नहीं करता है। और जो लोग इसे चेक करते हैं, वे आमतौर पर इसके पीछे तर्क को समझना मुश्किल लगेगा। लिनक्स में म्यूटेक्स कोड के लिए https://github.com/torvalds/linux/blob/master/kernel/locking/mutex.c देखें ... सौभाग्य से, यह अच्छी तरह से टिप्पणी की गई है। हालांकि, अभी भी जटिल है। जैसा कि मैंने कहा, * थोड़ा सा * गुप्त ... –

-1

मैंने System.Threading.ReaderWriterLockSlim के स्रोत को डीकंपाइल करने के लिए Reflector.NET का उपयोग किया, जिसे .NET Framework के हाल के संस्करण में जोड़ा गया था।

सिंक्रनाइज़ेशन प्राप्त करने के लिए यह अधिकतर Interlocked.CompareExchange, Thread.SpinWait और Thread.Sleep का उपयोग करता है। कुछ परिस्थितियों में कुछ EventWaitHandle (कर्नेल ऑब्जेक्ट) उदाहरण हैं जिनका उपयोग किया जाता है।

एक धागे पर पुनर्वितरण का समर्थन करने के लिए कुछ जटिलता भी जोड़ा गया है।

यदि आप इस क्षेत्र में रुचि रखते हैं और .NET (या कम से कम, इसे पढ़ सकते हैं) में काम कर रहे हैं तो आपको इस कक्षा को जांचना बहुत दिलचस्प लगेगा।

18

एडमस्की के test-and-set सुझाव पर बिल्डिंग, आपको "तेज उपयोगकर्ता-स्थान म्यूटेक्स" या futexes की अवधारणा को भी देखना चाहिए।

फ़्यूटेक्स की वांछनीय संपत्ति है कि उन्हें अनचाहे mutex को लॉक या अनलॉक करने के सामान्य मामलों में कर्नेल सिस्टम कॉल की आवश्यकता नहीं है। इन मामलों में, उपयोगकर्ता-मोड कोड mutex को लॉक या अनलॉक करने के लिए सफलतापूर्वक परमाणु compare and swap (CAS) ऑपरेशन का उपयोग करता है।

यदि सीएएस विफल रहता है, तो म्यूटेक्स का तर्क है और लिनक्स के तहत एक कर्नेल सिस्टम कॉल - sys_futex - या तो म्यूटेक्स (लॉक केस में) या अन्य थ्रेड (अनलॉक केस में) के लिए प्रतीक्षा करने के लिए इस्तेमाल किया जाना चाहिए। ।

यदि आप इसे स्वयं लागू करने के बारे में गंभीर हैं, तो सुनिश्चित करें कि आप Ulrich Drepper's paper भी पढ़ लें।

संबंधित मुद्दे