क्या आप बता सकते हैं कि सिंगल-कोर सीपीयू पर कई थ्रेड्स को ताले की आवश्यकता क्यों होती है?


18

मान लीजिए कि ये धागे सिंगल कोर सीपीयू में चलते हैं। एक सीपीयू के रूप में केवल एक चक्र में एक निर्देश चलाते हैं। यह कहा जाता है, यहां तक ​​कि सोचा कि वे सीपीयू संसाधन साझा करते हैं। लेकिन कंप्यूटर यह सुनिश्चित करता है कि एक बार एक निर्देश। तो क्या मल्टीथ्रेडिंग के लिए ताला आवश्यक नहीं है?


क्योंकि सॉफ़्टवेयर लेन-देन स्मृति अभी तक मुख्यधारा नहीं है।
dan_waterworth

@dan_waterworth क्योंकि गैर-तुच्छ जटिलता स्तरों पर सॉफ़्टवेयर ट्रांसेक्शनल मेमोरी बुरी तरह से विफल हो जाती है, आपका मतलब है? ;)
मेसन व्हीलर

मैं शर्त लगाऊंगा कि अमीर हिक्की इससे सहमत नहीं है।
रॉबर्ट हार्वे

@MasonWheeler, जबकि गैर-तुच्छ लॉकिंग आश्चर्यजनक रूप से अच्छी तरह से काम करता है और कभी सूक्ष्म कीड़े का स्रोत नहीं रहा है जो नीचे ट्रैक करना मुश्किल है? एसटीएम गैर-तुच्छ जटिलता स्तरों के साथ अच्छी तरह से काम करता है, लेकिन विवाद होने पर यह समस्याग्रस्त है। उन मामलों में, जैसे कुछ इस , जो एसटीएम के एक अधिक प्रतिबंधात्मक रूप है बेहतर है। Btw, शीर्षक परिवर्तन के साथ, मुझे यह पता लगाने के लिए काम करना पड़ा कि मैंने जैसा टिप्पणी की थी, वैसा ही क्यों किया।
dan_waterworth

जवाबों:


32

यह एक उदाहरण के साथ सबसे अच्छा सचित्र है।

मान लें कि हमारे पास एक सरल कार्य है जिसे हम समानांतर में कई बार प्रदर्शन करना चाहते हैं, और हम उस कार्य की संख्या को विश्व स्तर पर ट्रैक करना चाहते हैं, उदाहरण के लिए, एक वेब पेज पर हिट की गिनती।

जब प्रत्येक थ्रेड उस बिंदु पर पहुंच जाता है जिस पर वह गिनती बढ़ाता है, तो उसका निष्पादन इस तरह दिखाई देगा:

  1. प्रोसेसर रजिस्टर में मेमोरी से हिट की संख्या पढ़ें
  2. वह संख्या बढ़ाना।
  3. उस नंबर को मेमोरी में वापस लिखें

याद रखें कि हर धागा इस प्रक्रिया में किसी भी बिंदु पर निलंबित कर सकता है। इसलिए यदि थ्रेड ए चरण 1 करता है, और फिर निलंबित हो जाता है, थ्रेड बी द्वारा सभी तीन चरणों का पालन करते हुए, जब थ्रेड ए फिर से शुरू होता है, तो इसके रजिस्टरों में गलत संख्या हिट होगी: इसके रजिस्टरों को बहाल किया जाएगा, यह पुरानी संख्या को खुशी से बढ़ाएगा। हिट्स की, और उस बढ़े हुए नंबर को स्टोर करें।

इसके अलावा, किसी भी संख्या में अन्य थ्रेड उस समय के दौरान चल सकते थे जब थ्रेड A को निलंबित कर दिया गया था, इसलिए अंत में लिखने वाला थ्रेड A सही गणना के ठीक नीचे हो सकता है।

इस कारण से, यह सुनिश्चित करना आवश्यक है कि यदि कोई थ्रेड चरण 1 करता है, तो उसे स्टेप 3 करने से पहले किसी अन्य थ्रेड को चरण 1 करने की अनुमति है, जो कि इस प्रक्रिया को प्रारंभ करने से पहले एक भी लॉक प्राप्त करने की प्रतीक्षा कर रहे सभी थ्रेड द्वारा पूरा किया जा सकता है , और प्रक्रिया पूरी होने के बाद ही लॉक को मुक्त करना, ताकि कोड के इस "महत्वपूर्ण खंड" को गलत तरीके से इंटरलीव न किया जा सके, जिसके परिणामस्वरूप गलत गणना हो।

लेकिन क्या होगा अगर ऑपरेशन परमाणु थे?

हां, जादुई गेंडा और इंद्रधनुष की भूमि में, जहां वृद्धि ऑपरेशन परमाणु है, फिर उपरोक्त उदाहरण के लिए ताला लगाना आवश्यक नहीं होगा।

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

चूंकि, मल्टीथ्रेडेड कोड में भी, कई वेरिएबल्स को एक थ्रेड के लिए स्थानीय रखा जाता है, अगर वे प्रत्येक वैरिएबल को एक थ्रेड के लिए स्थानीय मान लेते हैं, तो प्रोग्राम बहुत अधिक कुशल होते हैं, और प्रोग्रामर थ्रेड्स के बीच साझा स्थिति की रक्षा करने का ध्यान रखते हैं। विशेष रूप से यह देखते हुए कि परमाणु संचालन आमतौर पर थ्रेडिंग मुद्दों को हल करने के लिए पर्याप्त नहीं है, जैसा कि हम बाद में देखेंगे।

अस्थिर चर

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

हम उस स्थिति में वापस आ सकते हैं, जिसे हमने पहले उदाहरण में दिया था (ऊपर बताई गई सभी समान थ्रेडिंग समस्याओं के साथ) चर को अस्थिर के रूप में चिह्नित करके , जो संकलक को बताता है कि यह चर दूसरों द्वारा संशोधित किया जा रहा है, और इसलिए इसे अवश्य पढ़ें या जब भी इसे एक्सेस या संशोधित किया जाता है, मेमोरी को लिखा जाता है।

तो अस्थिर के रूप में चिह्नित एक चर हमें परमाणु वृद्धि कार्यों की भूमि पर नहीं ले जाएगा, यह केवल हमें उतना ही करीब ले जाता है जितना हमने सोचा था कि हम पहले से ही थे।

वृद्धि को परमाणु बनाना

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

197       /**
198        * Atomically increments by one the current value.
199        *
200        * @return the updated value
201        */
202       public final int incrementAndGet() {
203           for (;;) {
204               int current = get();
205               int next = current + 1;
206               if (compareAndSet(current, next))
207                   return next;
208           }
209       }

उपरोक्त लूप बार-बार निम्न चरणों का पालन करता है, जब तक कि चरण 3 सफल न हो जाए:

  1. मेमोरी से सीधे वाष्पशील चर का मान पढ़ें।
  2. उस मूल्य में वृद्धि।
  3. मान को (मुख्य मेमोरी में) बदलें और यदि केवल मुख्य मेमोरी में इसका वर्तमान मान वैसा ही हो जैसा कि हम शुरू में पढ़ते हैं, तो एक विशेष परमाणु ऑपरेशन का उपयोग करके।

यदि चरण 3 विफल रहता है (क्योंकि चरण 1 के बाद एक अलग थ्रेड द्वारा मूल्य बदल दिया गया था), यह फिर से मुख्य मेमोरी से सीधे चर को पढ़ता है और फिर से कोशिश करता है।

जबकि तुलना-और-स्वैप ऑपरेशन महंगा है, इस मामले में लॉकिंग का उपयोग करने की तुलना में यह थोड़ा बेहतर है, क्योंकि यदि चरण 1 के बाद एक थ्रेड निलंबित हो जाता है, तो चरण 1 तक पहुंचने वाले अन्य थ्रेड्स को ब्लॉक नहीं करना पड़ता है और पहले थ्रेड का इंतजार करना पड़ता है, जो महंगा संदर्भ स्विचिंग को रोका जा सकता है। जब पहला धागा फिर से शुरू होता है, तो यह चर लिखने के अपने पहले प्रयास में विफल हो जाएगा, लेकिन चर को फिर से पढ़ना जारी रखने में सक्षम होगा, जो फिर से लॉक होने के साथ आवश्यक संदर्भ स्विच की तुलना में कम महंगा होगा।

इसलिए, हम वास्तविक ताले का उपयोग, तुलना और स्वैप के बिना परमाणु वृद्धि (या एक ही चर पर अन्य संचालन) की भूमि पर कर सकते हैं।

तो जब लॉकिंग सख्ती से आवश्यक है?

यदि आपको एक परमाणु संचालन में एक से अधिक चर को संशोधित करने की आवश्यकता है, तो लॉकिंग आवश्यक होगा, आपको उसके लिए एक विशेष प्रोसेसर निर्देश नहीं मिलेगा।

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

आइए एक उदाहरण पर विचार करें जहां प्रत्येक थ्रेड पहले चर एक्स में 2 जोड़ता है, और फिर एक्स को दो से गुणा करता है।

यदि X शुरू में एक है, और दो धागे चलते हैं, तो हम परिणाम ((1 + 2) * 2) + 2) * 2 = 16 होने की उम्मीद करते हैं।

हालाँकि, यदि थ्रेड्स इंटरलेवेव करते हैं, तो हम सभी ऑपरेशनों के परमाणु होने के बावजूद भी कर सकते हैं, इसके बजाय दोनों जोड़ पहले होते हैं, और गुणा के बाद आते हैं, जिसके परिणामस्वरूप (1 + 2 + 2) * 2 * 2 = 20 होता है।

ऐसा इसलिए होता है क्योंकि गुणन और जोड़ कम्यूटेटिव ऑपरेशन नहीं होते हैं।

इसलिए, खुद के परमाणु होने के लिए ऑपरेशन पर्याप्त नहीं है, हमें ऑपरेशन के संयोजन को परमाणु बनाना चाहिए।

हम या तो प्रक्रिया को क्रमबद्ध करने के लिए लॉकिंग का उपयोग करके कर सकते हैं, या हम एक स्थानीय चर का उपयोग कर सकते हैं जब हम अपनी गणना शुरू करते हैं, तो एक्स के मूल्य को संग्रहीत करने के लिए, मध्यवर्ती चरणों के लिए एक दूसरा स्थानीय चर, और फिर तुलना-और-स्वैप का उपयोग करें। केवल एक नया मान सेट करें यदि X का वर्तमान मान X के मूल मान के समान है। यदि हम विफल होते हैं, तो हमें X को पढ़ने और गणनाओं को फिर से निष्पादित करके फिर से शुरू करना होगा।

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

ताले के माध्यम से महत्वपूर्ण खंड का पूर्ण क्रमांकन उस स्थिति में बहुत बेहतर होगा: 99 धागे निलंबित होंगे जब उन्हें ताला नहीं मिला था, और हम लॉकिंग बिंदु पर आगमन के क्रम में प्रत्येक थ्रेड को चलाएंगे।

यदि क्रमांकन महत्वपूर्ण नहीं है (जैसा कि हमारे वेतन वृद्धि के मामले में), और गणना विफल हो जाती है यदि संख्या को अद्यतन करने में विफल रहता है तो न्यूनतम हैं, तुलनात्मक और स्वैप ऑपरेशन का उपयोग करने से प्राप्त होने वाला एक महत्वपूर्ण लाभ हो सकता है, क्योंकि वह ऑपरेशन ताला लगाने से कम खर्चीला है।


लेकिन क्या होगा अगर काउंटर श्मशान परमाणु है, क्या ताला आवश्यक था?
पायथोने

@pythonee: यदि काउंटर वृद्धि परमाणु है, तो संभवतः नहीं। लेकिन उचित आकार के किसी भी बहु-स्तरीय कार्यक्रम में आपके पास साझा संसाधन पर किए जाने वाले गैर-परमाणु कार्य होंगे।
डॉक्टर ब्राउन

1
जब तक आप वेतन वृद्धि को परमाणु बनाने के लिए एक संकलक का उपयोग नहीं कर रहे हैं, यह शायद नहीं है।
माइक लार्सन

हां, यदि रीड / संशोधित (वेतन वृद्धि) / लिखना परमाणु है, तो उस ऑपरेशन के लिए लॉक अनावश्यक है। DEC-10 AOSE (एक जोड़ें और छोड़ें यदि परिणाम == 0) निर्देश को विशेष रूप से परमाणु बनाया गया था, तो इसका उपयोग परीक्षण-और-सेट सेमाफोर के रूप में किया जा सकता है। मैनुअल का उल्लेख है कि यह काफी अच्छा था क्योंकि यह 36-बिट रजिस्टर को रोल ओवर करने के लिए मशीन को निरंतर गिनती के कई दिनों तक ले जाएगा। हालाँकि, आप जो कुछ भी नहीं करते हैं वह "मेमोरी में एक जोड़ें" होगा।
जॉन आर। स्ट्रॉहैम

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

4

इस उद्धरण पर विचार करें:

कुछ लोग, जब एक समस्या का सामना करते हैं, तो सोचते हैं, "मुझे पता है, मैं थ्रेड्स का उपयोग करूंगा," और फिर दो लोगों ने हब्बल डंप किया

आप देखते हैं, भले ही किसी भी समय सीपीयू पर 1 निर्देश चलता है, कंप्यूटर प्रोग्राम में केवल परमाणु विधानसभा निर्देशों की तुलना में बहुत अधिक शामिल हैं। इसलिए, उदाहरण के लिए, कंसोल (या एक फ़ाइल) पर लिखने का मतलब है कि आपको यह सुनिश्चित करने के लिए लॉक करना होगा कि आप जैसे चाहते हैं।


मैंने सोचा था कि भाव नियमित रूप से थे, धागे नहीं?
user16764

3
उद्धरण मेरे लिए थ्रेड्स के लिए बहुत अधिक लागू होता है (थ्रेडिंग मुद्दों के कारण शब्दों / वर्णों को क्रम से मुद्रित किया जा रहा है)। लेकिन वर्तमान में आउटपुट में एक अतिरिक्त "s" है, जो बताता है कि कोड में तीन समस्याएं हैं।
थियोडोर मर्डॉक

1
इसका एक दुष्परिणाम है। कभी-कभार आप 1 प्लस 1 जोड़ सकते हैं और 4294967295 :)
gbjbaanb

3

लगता है कि कई उत्तर लॉकिंग को समझाने का प्रयास करते हैं, लेकिन मुझे लगता है कि ओपी की जरूरत क्या मल्टीटास्किंग वास्तव में है की व्याख्या है।

जब आपके पास एक सीपीयू के साथ सिस्टम पर चलने वाले एक से अधिक थ्रेड होते हैं, तो दो मुख्य तरीके होते हैं जो यह निर्धारित करते हैं कि इन थ्रेड्स को कैसे शेड्यूल किया जाएगा (यानी आपके सिंगल-कोर सीपीयू में चलाने के लिए रखा गया है):

  • सहकारी मल्टीटास्किंग - Win9x में प्रयुक्त प्रत्येक एप्लिकेशन को स्पष्ट रूप से नियंत्रण छोड़ने के लिए आवश्यक है। इस मामले में, आपको लॉकिंग के बारे में चिंता करने की आवश्यकता नहीं होगी क्योंकि थ्रेड ए कुछ एल्गोरिथ्म को निष्पादित कर रहा है, आपको गारंटी दी जाएगी कि यह कभी भी बाधित नहीं होगा।
  • प्रीमेप्टिव मल्टीटास्किंग - अधिकांश आधुनिक ओएस (Win2k और बाद में) में उपयोग किया जाता है। यह समय का उपयोग करता है और थ्रेड को बाधित करेगा भले ही वे अभी भी काम कर रहे हों। यह बहुत अधिक मजबूत है क्योंकि एक भी धागा कभी भी आपकी पूरी मशीन को लटका नहीं सकता है, जो सहकारी मल्टीटास्किंग के साथ एक वास्तविक संभावना थी। दूसरी ओर, अब आपको तालों के बारे में चिंता करने की आवश्यकता है क्योंकि किसी भी समय, आपका एक थ्रेड बाधित हो सकता है (यानी पूर्व-निर्धारित) और OS चलाने के लिए एक अलग थ्रेड शेड्यूल कर सकता है। जब इस व्यवहार के साथ मल्टीट्र्रेड किए गए एप्लिकेशन को कोड करते हैं, तो आप यह अवश्य मानते हैं कि कोड की प्रत्येक पंक्ति (या यहां तक ​​कि प्रत्येक निर्देश) के बीच एक अलग थ्रेड चलता है। अब, एकल कोर के साथ भी, लॉकिंग आपके डेटा की सुसंगत स्थिति को सुनिश्चित करने के लिए बहुत महत्वपूर्ण हो जाता है।

0

समस्या व्यक्तिगत संचालन के साथ नहीं होती है, लेकिन बड़े कार्य संचालन को पूरा करते हैं।

कई एल्गोरिदम को इस धारणा के साथ लिखा जाता है कि वे जिस राज्य पर काम करते हैं, उसके पूर्ण नियंत्रण में हैं। आपके द्वारा वर्णित एक इंटरलेयर्ड ऑर्डर किए गए निष्पादन मॉडल के साथ, ऑपरेशन एक-दूसरे के साथ मध्यस्थता से हो सकते हैं, और यदि वे राज्य साझा करते हैं, तो एक जोखिम है कि राज्य असंगत आकार में है।

आप इसे उन कार्यों के साथ तुलना कर सकते हैं जो अस्थायी रूप से एक अपरिवर्तनीय को तोड़ सकते हैं ताकि वे क्या कर सकें। जब तक मध्यस्थ राज्य बाहर से देखने योग्य नहीं है, तब तक वे अपने कार्य को प्राप्त करने के लिए जो चाहें कर सकते हैं।

जब आप समवर्ती कोड लिखते हैं, तो आपको यह सुनिश्चित करने की आवश्यकता होती है कि जब तक आपके पास इसकी विशेष पहुंच न हो, तब तक इसे असुरक्षित माना जाता है। अनन्य उपयोग को प्राप्त करने का सामान्य तरीका एक ताला पकड़े हुए, तुल्यकालन आदिम पर सिंक्रनाइज़ हो रहा है।

एक और बात यह है कि सिंक्रोनाइज़ेशन प्राइमेटीज़ कुछ प्लेटफार्मों पर परिणामित होते हैं, वे मेमोरी बैरियर्स का उत्सर्जन करते हैं, जो मेमोरी के इंटर-सीपीयू स्थिरता सुनिश्चित करते हैं।


0

'बूल' सेट करने के अलावा कोई ग्वारंटी नहीं है (कम से कम c में) कि एक चर को पढ़ने या लिखने में केवल एक निर्देश लगता है - या इसे पढ़ने / लिखने के बीच में बाधित नहीं किया जा सकता है


32-बिट पूर्णांक लेने के लिए कितने निर्देश सेट करेंगे?
DXM नोव

1
क्या आप अपने पहले बयान पर थोड़ा विस्तार कर सकते हैं। आप का मतलब है कि केवल एक बूल परमाणु को पढ़ा / लिखा जा सकता है, लेकिन इसका कोई मतलब नहीं है। एक "बूल" वास्तव में हार्डवेयर में मौजूद नहीं है। यह आमतौर पर एक बाइट या एक शब्द के रूप में लागू किया जाता है, इस प्रकार केवल boolयह संपत्ति कैसे हो सकती है? और क्या आप मेमोरी से लोड करने, बदलने, और मेमोरी को वापस धकेलने के बारे में बात कर रहे हैं, या आप एक रजिस्टर स्तर पर बात कर रहे हैं? रजिस्टरों के लिए सभी पढ़ता / लिखता है, अबाधित है, लेकिन मेम लोड तब मेम स्टोर नहीं हैं (जैसा कि अकेले 2 निर्देश हैं, फिर मूल्य बदलने के लिए कम से कम 1 और)।
कोर्बिन नोव

1
हाइपरह्रेडेड / मल्टीकोर / ब्रांच-प्रेडिक्टेड / मल्टी-कैश्ड सीपीयू में एकल निर्देश की अवधारणा थोड़ी मुश्किल है - लेकिन मानक का कहना है कि केवल 'बूल' को रीड / राइट के बीच में एक संदर्भ स्विच के खिलाफ सुरक्षित होने की आवश्यकता है एक एकल चर की। एक बढ़ावा है :: परमाणु जो अन्य प्रकारों के आसपास म्यूटेक्स को लपेटता है और मुझे लगता है कि सी ++ 11 कुछ और सूत्रण ग्वारंटिस जोड़ता है
मार्टिन बेकेट

स्पष्टीकरण the standard says that only 'bool' needs to be safe against a context switch in the middle of a read/write of a single variableको वास्तव में उत्तर में जोड़ा जाना चाहिए।
वुल्फ

0

शेयर्ड मेमोरी।

यह की परिभाषा है ... धागे : समवर्ती प्रक्रियाओं का एक समूह, साझा स्मृति के साथ।

यदि कोई साझा मेमोरी नहीं है, तो उन्हें आमतौर पर पुराने स्कूल-यूनिक्स प्रक्रियाओं के रूप में संदर्भित किया जाता है।
हालाँकि, किसी साझा फ़ाइल को एक्सेस करते समय उन्हें एक लॉक की आवश्यकता हो सकती है।

(UNIX की तरह गुठली में साझा की गई मेमोरी को आम तौर पर साझा स्मृति पते का प्रतिनिधित्व करने वाले एक नकली फ़ाइल विवरणक का उपयोग करके लागू किया गया था)


0

एक CPU एक समय में एक निर्देश चलाता है, लेकिन क्या होगा यदि आपके पास दो या अधिक CPU हैं?

आप सही हैं कि तालों की जरूरत नहीं है, यदि आप प्रोग्राम को ऐसे लिख सकते हैं कि वह परमाणु निर्देशों का लाभ उठाता है: निर्देश जिनका निष्पादन दिए गए प्रोसेसर पर बाधित नहीं है, और अन्य प्रोसेसर द्वारा हस्तक्षेप से मुक्त है।

कई निर्देशों को हस्तक्षेप से बचाने की आवश्यकता होने पर ताले की आवश्यकता होती है, और कोई समान परमाणु निर्देश नहीं होता है।

उदाहरण के लिए, एक नोड को एक डबल-लिंक्ड सूची में सम्मिलित करने के लिए कई मेमोरी स्थानों के अपडेट की आवश्यकता होती है। सम्मिलन से पहले, और सम्मिलन के बाद, कुछ अपरिवर्तनीय लोग सूची की संरचना के बारे में पकड़ते हैं। हालांकि, सम्मिलन के दौरान, उन आक्रमणकारियों को अस्थायी रूप से तोड़ दिया जाता है: सूची "निर्माणाधीन" स्थिति में है।

यदि कोई अन्य थ्रेड सूची के माध्यम से मार्च करता है, या जब यह ऐसी स्थिति होती है, तो इसे संशोधित करने का भी प्रयास करता है, तो डेटा संरचना संभवतः दूषित हो जाएगी और व्यवहार अप्रत्याशित होगा: शायद सॉफ़्टवेयर क्रैश हो जाएगा, या गलत परिणामों के साथ जारी रहेगा। इसलिए यह आवश्यक है कि जब थ्रेड अपडेट किया जा रहा हो तो थ्रेड्स किसी तरह एक-दूसरे के रास्ते से बाहर रहने के लिए सहमत हों।

पर्याप्त रूप से डिज़ाइन की गई सूचियों को परमाणु निर्देशों के साथ हेरफेर किया जा सकता है, ताकि ताले की आवश्यकता न हो। इसके लिए एल्गोरिदम को "लॉक फ्री" कहा जाता है। हालांकि, ध्यान दें कि परमाणु निर्देश वास्तव में लॉकिंग का एक रूप है। वे विशेष रूप से हार्डवेयर में कार्यान्वित किए जाते हैं, और प्रोसेसर के बीच संचार के माध्यम से काम करते हैं। वे समान निर्देशों की तुलना में अधिक महंगे हैं जो परमाणु नहीं हैं।

मल्टीप्रोसेसर पर जिनके पास परमाणु निर्देशों की विलासिता की कमी होती है, पारस्परिक बहिष्कार के लिए आदिम को सरल मेमोरी एक्सेस और पोलिंग लूप का निर्माण करना पड़ता है। इस तरह की समस्याओं पर एग्जेर डीजकस्ट्रा और लेस्ली लामपोर्ट ने पसंद किया है।


FYI करें, मैंने केवल एकल तुलना-और-अदला-बदली का उपयोग करके डबल-लिंक्ड सूची अपडेट को संसाधित करने के लिए लॉक-फ्री एल्गोरिदम पढ़ा है। इसके अलावा, मैंने एक सुविधा के बारे में एक श्वेत पत्र पढ़ा, जो ऐसा प्रतीत होता है कि यह हार्डवेयर की तुलना में दोहरे-तुलना-और-स्वैप की तुलना में बहुत सस्ता होगा (जो 68040 में लागू किया गया था लेकिन अन्य 68xxx प्रोसेसर में नहीं था): लोड का विस्तार करें -लिंक किए गए / स्टोर-सशर्त दो लिंक्ड लोड और सशर्त स्टोर की अनुमति देने के लिए, लेकिन प्रोविज़ो के साथ कि दो दुकानों के बीच होने वाली एक पहुंच पहले वापस नहीं आएगी। डबल तुलना-और-स्टोर की तुलना में इसे लागू करना बहुत आसान है ...
सुपरकैट

... लेकिन दोहरे-लिंक-सूची अपडेट प्रबंधित करने का प्रयास करते समय समान लाभ प्रदान करेगा। जहां तक ​​मैं बता सकता हूं, डबल-लिंक्ड-लोड पर पकड़ा नहीं गया है, लेकिन अगर कोई मांग थी, तो हार्डवेयर लागत काफी सस्ती होगी।
सुपरकैट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.