2012-06-25 16 views
21

मैं स्मृति मॉडल को थोड़ा और देख रहा हूं और यह समझने में संघर्ष कर रहा हूं कि प्रक्रिया में कितने ढेर मौजूद हैं।ढेर और ढेर आवंटन

तो अगर हमारे पास 5 धागे के साथ 1 प्रक्रिया है, तो क्या मैं यह कहकर सही हूं कि हमारे पास 5 ढेर और 1 ढेर होगा?

यदि हां, तो धागे एक-दूसरे के ढेर तक पहुंच सकते हैं (या यही कारण है कि उनके पास भ्रष्टाचार को रोकने के लिए अलग-अलग ढेर हैं), और यदि वहां केवल 1 ढेर है, तो जाहिर है कि वे सभी इस ढेर तक पहुंचते हैं, इसलिए लॉकिंग की आवश्यकता एकाधिक धागे के साथ? क्या मुझे ये ठीक तरह से समझ आ रहा है?

उत्तर

31

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

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

एक और एक है कि आप पूरी तरह से प्रबंधित कोड में नजरअंदाज नहीं कर सकते ढेर कि स्थैतिक चर संग्रहीत करता है। यह ऐपडोमेन से जुड़ा हुआ है, जब तक ऐप्पडोमेन रहता है तब तक स्थैतिक चर रहते हैं। आम तौर पर नामित "लोडर ढेर" .NET साहित्य में। इसमें वास्तव में 3 ढेर होते हैं (उच्च आवृत्ति, कम आवृत्ति और स्टब ढेर), जिंद कोड और टाइप डेटा भी वहां संग्रहीत होता है लेकिन यह नटकिटी हो रहा है।

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

तो, न्यूनतम 10 ढेर।

12

संक्षेप में, हाँ

प्रक्रिया में सभी थ्रेड एक ही ढेर साझा करते हैं, इसलिए वे डेटा का आदान-प्रदान कर सकते हैं। प्रत्येक धागे का अपना ढेर होता है जो इस धागे पर वर्तमान कोड निष्पादन से संबंधित है।

सूत्रण पर एक बहुत अच्छा संसाधन यहाँ है: http://www.albahari.com/threading/

एक धागा ऑपरेटिंग सिस्टम प्रक्रिया के अनुरूप है, जिसमें अपने आवेदन रन है। जैसे ही कंप्यूटर पर समानांतर में चलती प्रक्रियाएं, धागे एक ही प्रक्रिया में समानांतर में चलती हैं। प्रक्रिया पूरी तरह से एक दूसरे से पृथक हैं; धागे में अलगाव की सीमित डिग्री है। विशेष रूप से, थ्रेड्स (हीप) मेमोरी को अन्य उसी एप्लिकेशन में चलने वाले धागे के साथ साझा करते हैं। यह, कुछ हद तक, थ्रेडिंग उपयोगी है: एक थ्रेड पृष्ठभूमि में डेटा को उदाहरण के लिए ला सकता है, जबकि कोई अन्य थ्रेड डेटा को प्रदर्शित कर सकता है।

+1

उत्कृष्ट लिंक के लिए धन्यवाद, वास्तव में अच्छा संसाधन है। – Richard

2

यह कार्यान्वयन परिभाषित किया गया है, लेकिन चलो सबसे लोकप्रिय आधुनिक ओएस के बारे में बात करते हैं, क्योंकि आप सी # टैग जोड़ते हैं।

किसी प्रक्रिया में कितने ढेर मौजूद हैं।

आमतौर पर 1 प्रति प्रक्रिया।

तो अगर हमारे पास 5 धागे के साथ 1 प्रक्रिया है, तो क्या मैं यह कहकर सही हूं कि हमारे पास 5 ढेर और 1 ढेर होगा?

हां। प्रत्येक थ्रेड सीधे थ्रेड स्टैक के लिए 1 एमबी वर्चुअल एड्रेस स्पेस का उपभोग करता है।

यदि हां, तो धागे एक दूसरे के ढेर का उपयोग कर सकते हैं (या है यह वास्तव में क्यों वे अलग ढेर है, भ्रष्टाचार को रोकने के लिए), और अगर वहाँ सिर्फ 1 ढेर जाहिर है कि वे सभी का उपयोग इस ढेर की जरूरत है, तो है, इसलिए एकाधिक धागे के साथ लॉक करने के लिए? क्या मुझे ये ठीक तरह से समझ आ रहा है?

हां, आधुनिक वातावरण बहुत अच्छी तरह से sandboxed हैं, इसलिए आप सीधे अन्य धागे से अन्य थ्रेड स्टैक तक नहीं पहुंच सकते हैं।

+0

लुकास ने आपको Jakub-Konecki जवाब देखा था? यह कैसे "के साथ सहसंबंध करता है ... इसलिए आप अन्य थ्रेड स्टैक तक नहीं पहुंच सकते" ?? और क्यों 'लॉकिंग' तंत्र मौजूद है? – Jasper

+0

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

+1

नाइटपिकिंग: एक प्रक्रिया में (सामान्य) प्रबंधित हेप, एक बड़ा ऑब्जेक्ट हीप होता है और आप अप्रबंधित ढेर # 3 होने पर विचार कर सकते हैं। –

4

थ्रेड एक ही प्रक्रिया के समान वर्चुअल एड्रेस स्पेस में एक साथ चल रहे अलग-अलग निर्देश स्ट्रीम हैं। हीप स्मृति का एक बड़ा हिस्सा है कि प्रणाली प्रत्येक प्रक्रिया को अपने निजी उपयोग के लिए देती है। प्रक्रियाएं उनके ढेर के आकार को समायोजित कर सकती हैं और ढेर की जगह का उपयोग कर सकती हैं क्योंकि उन्हें आवश्यक समझा जाता है।थ्रेड इस ढेर स्पेस का उपयोग करने में सहयोग कर सकते हैं और थ्रेड स्थानीय स्टोरेज (TLSes) के रूप में जाने वाले अतिरिक्त निजी मेमोरी क्षेत्रों को भी आवंटित कर सकते हैं।

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

सी और सी ++ में प्रक्रिया स्मृति के हर हिस्से अप्रबंधित भाषाओं में संकेत के उपयोग के माध्यम होगा पर पहुँचा जा सकता है। एक थ्रेड पूरी तरह से किसी अन्य थ्रेड के ढेर की सामग्री के साथ गड़बड़ कर सकता है और इस प्रकार दूसरे धागे को क्रैश कर सकता है (और पूरी तरह से प्रक्रिया)। सी # में इन प्रकार की चीजें unsafe ब्लॉक के बाहर नहीं हो सकती हैं क्योंकि सीएलआर द्वारा ढेर किए जाते हैं।

+0

_one थ्रेड किसी अन्य थ्रेड_ में चल रहे फ़ंक्शन के तर्क के रूप में एक चर को अपने चरम पर पास कर सकता है - आप इसे कैसे ठीक करेंगे? –

+0

Win32 थ्रेड के साथ आप बस एक नया धागा शुरू कर सकते हैं और मौजूदा थ्रेड में स्थानीय चर के पते को थ्रेड तर्क के रूप में पास कर सकते हैं। आप पहले से चल रहे थ्रेड को संदेश भेजने के लिए 'PostThreadMessage' का भी उपयोग कर सकते हैं। –

+0

दोनों दृष्टिकोणों के लिए एक सूचक की आवश्यकता होगी। –

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