मुझे लगता है कि दोनों एक ही काम कर रहे हैं, आप कैसे तय करते हैं कि किसको सिंक्रोनाइज़ेशन के लिए इस्तेमाल करना है?
मुझे लगता है कि दोनों एक ही काम कर रहे हैं, आप कैसे तय करते हैं कि किसको सिंक्रोनाइज़ेशन के लिए इस्तेमाल करना है?
जवाबों:
सिद्धांत
सिद्धांत रूप में, जब एक थ्रेड म्यूटेक्स को लॉक करने की कोशिश करता है और यह सफल नहीं होता है, क्योंकि म्यूटेक्स पहले से ही लॉक है, यह सो जाएगा, तुरंत एक और थ्रेड को चलाने की अनुमति देगा। जागने तक यह सोता रहेगा, जो कि एक बार म्यूटेक्स को अनलॉक करने से पहले जो भी धागा लॉक हो रहा था, उसे अनलॉक किया जाएगा। जब कोई थ्रेड स्पिनलॉक लॉक करने की कोशिश करता है और यह सफल नहीं होता है, तो वह इसे लॉक करने की लगातार कोशिश करेगा, जब तक कि यह अंत में सफल नहीं हो जाता; इस प्रकार यह एक अन्य धागे को अपनी जगह लेने की अनुमति नहीं देगा (हालांकि, ऑपरेटिंग सिस्टम दूसरे धागे पर बलपूर्वक स्विच करेगा, एक बार वर्तमान धागे का सीपीयू रनटाइम क्वांटम को पार कर गया है)।
समस्या
म्यूटेक्स के साथ समस्या यह है कि थ्रेड्स को सोने के लिए रखना और उन्हें फिर से जागना दोनों ही महंगे ऑपरेशन हैं, उन्हें सीपीयू के काफी निर्देशों की आवश्यकता होगी और इस तरह कुछ समय भी लगेगा। यदि अब म्यूटेक्स केवल बहुत कम समय के लिए बंद हो गया था, तो सोने के लिए एक धागा लगाने और उसे फिर से जागने में बिताया गया समय उस समय से अधिक हो सकता है जब धागा वास्तव में दूर तक सोया हो और यह उस समय से अधिक हो सकता है जब धागा होगा एक पालक पर लगातार मतदान से बर्बाद कर दिया है। दूसरी ओर, एक पालक पर मतदान लगातार सीपीयू समय बर्बाद करेगा और अगर लॉक को अधिक समय तक आयोजित किया जाता है, तो यह बहुत अधिक सीपीयू समय बर्बाद करेगा और यह बेहतर होगा यदि धागा इसके बजाय सो रहा था।
समाधान
सिंगल-कोर / सिंगल-सीपीयू सिस्टम पर स्पिनलॉक का उपयोग करना आमतौर पर कोई मतलब नहीं रखता है, क्योंकि जब तक स्पिनलॉक मतदान केवल उपलब्ध सीपीयू कोर को रोक रहा है, कोई अन्य धागा नहीं चल सकता है और चूंकि कोई अन्य धागा नहीं चल सकता है, इसलिए लॉक नहीं होगा या तो अनलॉक हो। IOW, बिना वास्तविक लाभ के उन प्रणालियों पर केवल एक CPU समय बर्बाद करता है। यदि धागे को सोने के लिए रखा जाता था, तो एक और धागा एक बार में चल सकता था, संभवतः ताला को अनलॉक कर सकता था और फिर पहले धागे को प्रसंस्करण जारी रखने की अनुमति देता था, एक बार फिर से जाग गया।
मल्टी-कोर / मल्टी-सीपीयू सिस्टम पर, बहुत सारे तालों के साथ, जो केवल बहुत कम समय के लिए आयोजित किए जाते हैं, लगातार सोने के लिए धागे डालने और उन्हें फिर से जगाने के लिए व्यर्थ होने वाले समय में रनटाइम प्रदर्शन में कमी हो सकती है। इसके बजाय स्पिनलॉक का उपयोग करते समय, थ्रेड्स को अपने पूर्ण रनटाइम क्वांटम (हमेशा केवल बहुत कम समय के लिए अवरुद्ध होने पर, लेकिन फिर तुरंत अपना काम जारी रखने) का लाभ उठाने का मौका मिलता है, जिससे बहुत अधिक प्रसंस्करण थ्रूपुट होता है।
अभ्यास
चूंकि बहुत बार प्रोग्रामर अग्रिम में नहीं जान सकते हैं कि म्यूटेक्स या स्पिनलॉक बेहतर होंगे (जैसे कि लक्ष्य वास्तुकला की सीपीयू कोर की संख्या अज्ञात है), और न ही ऑपरेटिंग सिस्टम यह जान सकते हैं कि क्या एक निश्चित कोड को सिंगल-कोर के लिए अनुकूलित किया गया है या मल्टी-कोर वातावरण, अधिकांश सिस्टम म्यूटेक्स और स्पिनलॉक के बीच कड़ाई से अंतर नहीं करते हैं। वास्तव में, अधिकांश आधुनिक ऑपरेटिंग सिस्टम में हाइब्रिड म्यूटेक्स और हाइब्रिड स्पिनलॉक होते हैं। वास्तव में इसका क्या मतलब है?
एक हाइब्रिड म्यूटेक्स एक मल्टी-कोर सिस्टम पर पहली बार एक स्पिनलॉक की तरह व्यवहार करता है। यदि कोई धागा म्यूटेक्स को लॉक नहीं कर सकता है, तो उसे तुरंत सोने के लिए नहीं रखा जाएगा, क्योंकि म्यूटेक्स बहुत जल्द अनलॉक हो सकता है, इसलिए इसके बजाय म्यूटेक्स पहले एक स्पिनलॉक की तरह व्यवहार करेगा। केवल अगर ताला अभी भी एक निश्चित समय (या रिट्रीट या किसी अन्य मापने वाले कारक) के बाद प्राप्त नहीं किया गया है, तो धागा वास्तव में सोने के लिए डाल दिया जाता है। यदि समान कोड केवल सिंगल कोर वाले सिस्टम पर चलता है, तो म्यूटेक्स स्पिन नहीं करेगा, हालांकि, जैसा कि, ऊपर देखें, यह फायदेमंद नहीं होगा।
एक हाइब्रिड स्पिनलॉक एक सामान्य स्पिनलॉक की तरह व्यवहार करता है, लेकिन बहुत अधिक सीपीयू समय बर्बाद करने से बचने के लिए, यह एक बैक-ऑफ रणनीति हो सकती है। यह आमतौर पर थ्रेड को सोने के लिए नहीं देगा (क्योंकि आप नहीं चाहते हैं कि स्पिनलॉक का उपयोग करते समय ऐसा हो), लेकिन यह थ्रेड को रोकने का निर्णय ले सकता है (या तो तुरंत या निश्चित समय के बाद) और किसी अन्य थ्रेड को चलाने की अनुमति दें , इस प्रकार संभावना बढ़ जाती है कि स्पिनलॉक अनलॉक किया गया है (एक शुद्ध धागा स्विच आमतौर पर एक से कम महंगा होता है जिसमें सोने के लिए एक धागा डालना और बाद में फिर से जागना शामिल होता है, हालांकि दूर तक नहीं)।
सारांश
यदि संदेह है, तो म्यूटेक्स का उपयोग करें, वे आमतौर पर बेहतर विकल्प होते हैं और अधिकांश आधुनिक प्रणालियां उन्हें बहुत कम समय के लिए स्पिन करने देती हैं, अगर यह फायदेमंद लगता है। स्पिनलॉक का उपयोग करना कभी-कभी प्रदर्शन में सुधार कर सकता है, लेकिन केवल कुछ शर्तों के तहत और तथ्य यह है कि आप संदेह में हैं, बल्कि मुझे बताता है, कि आप वर्तमान में किसी भी प्रोजेक्ट पर काम नहीं कर रहे हैं, जहां एक स्पिनलॉक फायदेमंद हो सकता है। आप अपनी स्वयं की "लॉक ऑब्जेक्ट" का उपयोग करने पर विचार कर सकते हैं, या तो आंतरिक रूप से एक स्पिनलॉक या म्यूटेक्स का उपयोग कर सकते हैं (जैसे कि इस तरह की वस्तु बनाते समय यह व्यवहार कॉन्फ़िगर किया जा सकता है), शुरू में हर जगह म्यूटेक्स का उपयोग करें और अगर आपको लगता है कि स्पिनक का उपयोग करना वास्तव में कहीं हो सकता है मदद करें, इसे आज़माएं और परिणामों की तुलना करें (उदाहरण के लिए एक प्रोफाइलर का उपयोग करके), लेकिन दोनों मामलों का परीक्षण करना सुनिश्चित करें,
वास्तव में iOS विशिष्ट नहीं बल्कि iOS वह प्लेटफ़ॉर्म है जहां अधिकांश डेवलपर्स उस समस्या का सामना कर सकते हैं: यदि आपके सिस्टम में थ्रेड शेड्यूलर है, तो यह गारंटी नहीं देता है कि कोई भी थ्रेड, चाहे उसकी प्राथमिकता कितनी भी कम क्यों न हो, अंततः उसे चलाने का मौका मिलेगा, फिर स्पिनलॉक से स्थायी गतिरोध हो सकता है। IOS अनुसूचक धागे के विभिन्न वर्गों को अलग करता है और निम्न वर्ग के धागे केवल तभी चलेंगे यदि कोई उच्च वर्ग में कोई भी धागा नहीं चलाना चाहता है। इसके लिए कोई बैक-ऑफ रणनीति नहीं है, इसलिए यदि आपके पास स्थायी रूप से उच्च श्रेणी के थ्रेड उपलब्ध हैं, तो निम्न श्रेणी के थ्रेड्स को कभी भी सीपीयू समय नहीं मिलेगा और इस प्रकार किसी भी कार्य को करने का कोई मौका नहीं मिलेगा।
समस्या निम्नानुसार दिखाई देती है: आपका कोड निम्न प्रियो वर्ग के धागे में एक स्पिनलॉक प्राप्त करता है और जबकि यह उस लॉक के बीच में होता है, समय क्वांटम से अधिक हो गया है और थ्रेड चलना बंद हो जाता है। इस स्पिनलॉक को फिर से कैसे जारी किया जा सकता है, इसका एकमात्र तरीका यह है कि निम्न प्रोटो क्लास थ्रेड को फिर से सीपीयू समय मिले, लेकिन ऐसा होने की गारंटी नहीं है। आपके पास उच्च बेशुमार क्लास थ्रेड्स की एक जोड़ी हो सकती है जो लगातार चलाना चाहते हैं और कार्य अनुसूचक हमेशा उन लोगों को प्राथमिकता देगा। उनमें से एक पालक के पार चल सकता है और इसे प्राप्त करने का प्रयास कर सकता है, जो कि संभव नहीं है, और सिस्टम इसे उपज देगा। समस्या यह है: एक धागा जो फिर से चलाने के लिए तुरंत उपलब्ध है! लॉक रखने वाले थ्रेड की तुलना में अधिक प्रियो होने से, लॉक को रखने वाले थ्रेड के पास सीपीयू रनटाइम प्राप्त करने का कोई मौका नहीं है।
म्यूटेक्स के साथ यह समस्या क्यों नहीं होती है? जब उच्च बेशुमार धागा म्यूटेक्स प्राप्त नहीं कर सकता है, तो यह उपज नहीं देगा, यह थोड़ा घूम सकता है लेकिन अंततः सोने के लिए भेजा जाएगा। एक नींद का धागा चलाने के लिए उपलब्ध नहीं है जब तक कि यह एक घटना से नहीं जागता है, उदाहरण के लिए म्यूटेक्स जैसी घटना को अनलॉक किया जा रहा है। Apple उस समस्या से अवगत है और इस प्रकार OSSpinLock
परिणाम के रूप में हटा दिया गया है । नया ताला कहा जाता है os_unfair_lock
। यह लॉक ऊपर वर्णित स्थिति से बचा जाता है क्योंकि यह विभिन्न थ्रेड प्राथमिकता वर्गों के बारे में जानता है। यदि आप सुनिश्चित हैं कि स्पिनलॉक का उपयोग करना आपके आईओएस प्रोजेक्ट में एक अच्छा विचार है, तो इसका उपयोग करें। से दूर रहोOSSpinLock
! और किसी भी परिस्थिति में आईओएस में अपने स्वयं के स्पिनलॉक को लागू न करें! यदि संदेह है, तो एक म्यूटेक्स का उपयोग करें! MacOS इस समस्या से प्रभावित नहीं है क्योंकि इसमें एक अलग थ्रेड शेड्यूलर है जो CPU समय पर किसी भी थ्रेड (यहां तक कि कम बेशकीमती धागे) को "सूखा" चलाने की अनुमति नहीं देगा, फिर भी वही स्थिति उत्पन्न हो सकती है और फिर बहुत खराब हो जाएगी प्रदर्शन, इस प्रकार OSSpinLock
macOS पर भी पदावनत किया जाता है।
मेकी के सुझाव के साथ जारी रखते हुए, यह लेख अलेक्जेंडर सैंडलर के ब्लॉग पर म्यूटेक्स बनाम pthread spinlock , लिनक्स पर एलेक्स दिखाता है कि #ifdef का उपयोग करके व्यवहार का परीक्षण करने के लिए spinlock
& कैसे mutexes
कार्यान्वित किया जा सकता है।
हालांकि, अपने अवलोकन के आधार पर अंतिम कॉल लेना सुनिश्चित करें, दिए गए उदाहरण के रूप में समझना एक अलग मामला है, आपकी परियोजना की आवश्यकता, पर्यावरण पूरी तरह से अलग हो सकता है।
कृपया यह भी ध्यान दें कि कुछ वातावरण और स्थितियों पर (जैसे डिस्पैच स्तर पर खिड़कियों पर चलना> = छूट स्तर), आप म्यूटेक्स का उपयोग नहीं कर सकते हैं, बल्कि स्पिनकॉक का उपयोग कर सकते हैं। यूनिक्स पर - एक ही बात।
यहाँ प्रतियोगी स्टेक्सएक्सचेंज यूनिक्स साइट पर समान प्रश्न है: /unix/5107/why-are-spin-locks-good-choices-in-linux-kernel-design-instead-of-something- अधिक
विंडोज़ सिस्टम पर प्रेषण पर जानकारी: http://download.microsoft.com/download/e/b/eba1050f-a31d-436b-9281-92cdfeae4b45/IRQL_thread.oc
Mecki का जवाब बहुत अच्छी तरह से यह नाखून। हालाँकि, एक एकल प्रोसेसर पर, स्पिनलॉक का उपयोग करने से समझ में आ सकता है जब कार्य एक इंटर सर्विस सर्विस रूटीन द्वारा दिए जाने वाले लॉक का इंतजार कर रहा है। व्यवधान ISR पर नियंत्रण स्थानांतरित कर देगा, जो प्रतीक्षा कार्य द्वारा उपयोग के लिए संसाधन तैयार करेगा। यह बाधित कार्य पर वापस नियंत्रण देने से पहले ताला जारी करने से समाप्त होगा। कताई कार्य को उपलब्ध कताई मिल जाएगा और आगे बढ़ना होगा।
स्पिनलॉक और म्यूटेक्स सिंक्रोनाइज़ेशन मैकेनिज़्म को देखा जाना आज बहुत आम है।
आइए पहले स्पिनलॉक के बारे में सोचते हैं।
मूल रूप से यह एक व्यस्त प्रतीक्षा कार्रवाई है, जिसका अर्थ है कि हमें अगली कार्रवाई के आगे बढ़ने से पहले एक निर्दिष्ट लॉक के लिए इंतजार करना होगा। वैचारिक रूप से बहुत सरल है, जबकि इसे लागू करना मामले पर नहीं है। उदाहरण के लिए: यदि ताला जारी नहीं किया गया है, तो धागा स्वैप-आउट हो गया और नींद की स्थिति में आ गया, क्या हमें इससे निपटना चाहिए? जब दो धागे एक साथ पहुंच का अनुरोध करते हैं तो सिंक्रोनाइज़ेशन लॉक से कैसे निपटें?
आम तौर पर, सबसे सहज विचार महत्वपूर्ण खंड की सुरक्षा के लिए एक चर के माध्यम से सिंक्रनाइज़ेशन के साथ काम कर रहा है। म्यूटेक्स की अवधारणा समान है, लेकिन वे अभी भी अलग हैं। फोकस: सीपीयू उपयोग। स्पिनलॉक सीपीयू समय का उपभोग करने के लिए प्रतीक्षा करता है, और इसलिए, हम दोनों के बीच अंतर को योग कर सकते हैं:
सजातीय बहु-कोर वातावरण में, यदि महत्वपूर्ण खंड पर समय स्पिनलॉक के उपयोग से छोटा है, क्योंकि हम संदर्भ स्विच समय को कम कर सकते हैं। (सिंगल-कोर तुलना महत्वपूर्ण नहीं है, क्योंकि कुछ सिस्टम स्विच के बीच में स्पिनलॉक लागू करते हैं)
विंडोज में, स्पिनलॉक का उपयोग करके थ्रेड को DISPATCH_LEVEL में अपग्रेड किया जाएगा, जिसे कुछ मामलों में अनुमति नहीं दी जा सकती है, इसलिए इस बार हमें म्यूटेक्स (APC_LEVEL) का उपयोग करना था।
सिंगल-कोर / सिंगल-सीपीयू सिस्टम पर स्पिनलॉक का उपयोग करना आमतौर पर कोई मतलब नहीं रखता है, क्योंकि जब तक स्पिनलॉक मतदान केवल उपलब्ध सीपीयू कोर को रोक रहा है, कोई अन्य धागा नहीं चल सकता है और चूंकि कोई अन्य धागा नहीं चल सकता है, इसलिए लॉक नहीं होगा या तो अनलॉक हो। IOW, बिना वास्तविक लाभ के उन प्रणालियों पर केवल एक CPU समय बर्बाद करता है
ये गलत है। यूनी प्रोसेसर सिस्टम पर स्पिनलॉक का उपयोग करने में सीपीयू चक्रों का कोई अपव्यय नहीं है, क्योंकि एक बार एक प्रक्रिया एक स्पिन लॉक लेती है, प्रीमेशन को निष्क्रिय कर दिया जाता है, इसलिए जैसे, कोई और नहीं हो सकता है! यह सिर्फ इतना है कि इसका उपयोग करने का कोई मतलब नहीं है! इसलिए, यूनी सिस्टम पर स्पिनलॉक को कर्नेल द्वारा संकलन समय पर preempt_disable द्वारा प्रतिस्थापित किया जाता है!