हालांकि एक म्यूटेक्स का उपयोग अन्य समस्याओं को हल करने के लिए किया जा सकता है, उनके पास मौजूद प्राथमिक कारण आपसी बहिष्कार प्रदान करना है और इस तरह हल करना जो एक दौड़ की स्थिति के रूप में जाना जाता है। जब दो (या अधिक) धागे या प्रक्रियाएं समान रूप से एक ही चर का उपयोग करने का प्रयास कर रही हैं, तो हमारे पास दौड़ की स्थिति के लिए क्षमता है। निम्नलिखित कोड पर विचार करें
//somewhere long ago, we have i declared as int
void my_concurrently_called_function()
{
i++;
}
इस फ़ंक्शन के इंटर्नल्स बहुत सरल दिखते हैं। यह केवल एक बयान है। हालाँकि, एक सामान्य छद्म विधानसभा भाषा समकक्ष हो सकती है:
load i from memory into a register
add 1 to i
store i back into memory
क्योंकि समतुल्य असेंबली-भाषा निर्देश सभी के लिए irement ऑपरेशन करने के लिए आवश्यक हैं, हम कहते हैं कि incrementing i एक गैर-atmoic ऑपरेशन है। एक परमाणु ऑपरेशन वह है जिसे निर्देश निष्पादन शुरू होने के बाद एक बार बाधित नहीं होने के गुरंट्टी के साथ हार्डवेयर पर पूरा किया जा सकता है। वृद्धि में 3 परमाणु निर्देशों की एक श्रृंखला शामिल है। एक समवर्ती प्रणाली में जहां कई थ्रेड्स फ़ंक्शन को बुला रहे हैं, समस्या तब उत्पन्न होती है जब कोई थ्रेड गलत समय पर पढ़ता या लिखता है। कल्पना करें कि हमारे पास एक साथ चलने वाले दो धागे हैं और एक दूसरे के तुरंत बाद फ़ंक्शन को कॉल करता है। हम यह भी कहते हैं कि हमने 0. को इनिशियलाइज़ किया है। यह भी मान लें कि हमारे पास बहुत सारे रजिस्टर हैं और यह कि दो धागे पूरी तरह से अलग रजिस्टरों का उपयोग कर रहे हैं, इसलिए कोई टकराव नहीं होगा। इन घटनाओं का वास्तविक समय हो सकता है:
thread 1 load 0 into register from memory corresponding to i //register is currently 0
thread 1 add 1 to a register //register is now 1, but not memory is 0
thread 2 load 0 into register from memory corresponding to i
thread 2 add 1 to a register //register is now 1, but not memory is 0
thread 1 write register to memory //memory is now 1
thread 2 write register to memory //memory is now 1
क्या हुआ है कि हमारे पास दो सूत्र हैं जो कि मैं समवर्ती रूप से बढ़ाता हूं, हमारे कार्य को दो बार कहा जाता है, लेकिन परिणाम उस तथ्य के साथ असंगत है। ऐसा लगता है कि फ़ंक्शन केवल एक बार बुलाया गया था। ऐसा इसलिए है क्योंकि मशीन स्तर पर परमाणु "टूट" गया है, जिसका अर्थ है कि धागे एक-दूसरे को बाधित कर सकते हैं या गलत समय पर एक साथ काम कर सकते हैं।
हमें इसे हल करने के लिए एक तंत्र की आवश्यकता है। हमें ऊपर दिए गए निर्देशों को कुछ आदेश देने की आवश्यकता है। एक सामान्य तंत्र एक को छोड़कर सभी थ्रेड्स को ब्लॉक करना है। Pthread mutex इस तंत्र का उपयोग करता है।
किसी भी धागे को कोड की कुछ पंक्तियों को निष्पादित करना होगा जो एक ही समय में अन्य थ्रेड्स द्वारा साझा किए गए मानों को अनसुना रूप से संशोधित कर सकते हैं (अपनी पत्नी से बात करने के लिए फोन का उपयोग करके), पहले एक म्यूटेक्स पर लॉक प्राप्त करना चाहिए। इस तरह, किसी भी थ्रेड को साझा किए गए डेटा तक पहुंचने के लिए म्यूटेक्स लॉक से गुजरना होगा। तभी एक धागा कोड को निष्पादित करने में सक्षम होगा। कोड के इस अनुभाग को एक महत्वपूर्ण अनुभाग कहा जाता है।
एक बार जब थ्रेड महत्वपूर्ण खंड को निष्पादित कर लेता है, तो उसे म्यूटेक्स पर लॉक को छोड़ देना चाहिए ताकि एक और धागा म्यूटेक्स पर लॉक प्राप्त कर सके।
एक म्यूटेक्स होने की अवधारणा थोड़ी अजीब लगती है जब मनुष्य वास्तविक, भौतिक वस्तुओं के लिए विशेष रूप से उपयोग करने पर विचार करता है, लेकिन जब प्रोग्रामिंग, हमें जानबूझकर होना चाहिए। समवर्ती धागे और प्रक्रियाओं में सामाजिक और सांस्कृतिक परवरिश नहीं होती है जो हम करते हैं, इसलिए हमें उन्हें डेटा को अच्छी तरह से साझा करने के लिए मजबूर करना चाहिए।
तो तकनीकी रूप से, एक म्यूटेक्स कैसे काम करता है? क्या यह उसी दौड़ की स्थिति से ग्रस्त नहीं है जिसका हमने पहले उल्लेख किया था? क्या pthread_mutex_lock () थोड़ा अधिक जटिल है जो एक चर का एक साधारण वेतन वृद्धि है?
तकनीकी रूप से कहें तो हमें मदद करने के लिए कुछ हार्डवेयर सपोर्ट की जरूरत होती है। हार्डवेयर डिज़ाइनर हमें मशीन निर्देश देते हैं जो एक से अधिक काम करते हैं लेकिन परमाणु होने के लिए गुरुंटेड हैं। इस तरह के निर्देश का एक क्लासिक उदाहरण परीक्षण-और-सेट (टीएएस) है। संसाधन पर लॉक प्राप्त करने का प्रयास करते समय, हम TAS का उपयोग यह देखने के लिए कर सकते हैं कि क्या स्मृति में मान 0. है। यदि यह है, तो यह हमारा संकेत होगा कि संसाधन उपयोग में है और हम कुछ भी नहीं करते हैं (या अधिक सटीक) , हम कुछ तंत्र द्वारा प्रतीक्षा करते हैं। एक pthreads mutex हमें ऑपरेटिंग सिस्टम में एक विशेष कतार में डाल देगा और संसाधन उपलब्ध होने पर हमें सूचित करेगा। डम्बर सिस्टम को एक तंग स्पिन लूप करने की आवश्यकता हो सकती है, स्थिति को बार-बार परीक्षण कर सकते हैं) । यदि स्मृति में मान 0 नहीं है, तो TAS किसी भी अन्य निर्देशों का उपयोग किए बिना 0 के अलावा किसी अन्य स्थान पर सेट करता है। यह हमें परमाणुता देने के लिए 1 में दो विधानसभा निर्देशों के संयोजन की तरह है। इस प्रकार, परीक्षण और मूल्य बदलना (यदि बदलना उचित है) एक बार शुरू होने के बाद बाधित नहीं किया जा सकता है। हम इस तरह के निर्देश के शीर्ष पर म्यूटेक्स का निर्माण कर सकते हैं।
नोट: कुछ खंड पहले के उत्तर के समान दिखाई दे सकते हैं। मैंने संपादित करने के लिए उनके निमंत्रण को स्वीकार किया, उन्होंने मूल तरीका पसंद किया, इसलिए मैं वही रख रहा हूं जो मेरे पास था, जो कि उनके क्रिया-कलापों से थोड़ा प्रभावित है।