6

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

इसके अलावा यह मेरी समझ है कि अस्थिरता थ्रेड सुरक्षा की गारंटी नहीं देती है। क्या यह सच है?

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

HANDLE hThread = CreateThread(NULL, 0, thread_entry, (void *)&data, CREATE_SUSPENDED, NULL); 
data->val64 = SomeCalculation(); 
ResumeThread(hThread); 

मुझे लगता है यह किसी भी पर निर्भर करेगा:

इसलिए उदाहरण के लिए मान लीजिए कि मैं एक धागा निलंबित बनाने के लिए, उदाहरण के लिए, थ्रेड में कोई struct उपलब्ध करने के लिए कुछ मूल्यों को बदल और उसके बाद फिर से शुरू करने के लिए कुछ गणना करते हैं रेज़्यूमे थ्रेड में मेमोरी बाधाएं? क्या मुझे val64 के लिए एक इंटरलॉक एक्सचेंज करना चाहिए? क्या होगा अगर धागा चल रहा था, यह चीजों को कैसे बदलता है?

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

+0

'अस्थिर' का मतलब केवल एक चीज है - एक चर के लिए बार-बार उपयोग को अनुकूलित न करें। यह परमाणुता या ऑपरेशन रीडरिंग या कैश कोहेरेंसी पर कोई संयम नहीं रखता है। –

उत्तर

6

इसे बनाने के लिए प्रयोग किया जाता है सुनिश्चित करें कि एक मूल्य पूरे

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

संरेखित अपडेट हो रही है, बहुत आसान है यह संकलक द्वारा प्रदान की गारंटी नहीं है। या, अधिक मोटे तौर पर, स्मृति मॉडल के आधार पर संकलक द्वारा कार्यान्वित। जो मेमोरी पतों को आसानी से चुनता है जो गठबंधन होते हैं, कभी-कभी जानबूझकर कुछ बाइट्स के अप्रयुक्त अंतराल को छोड़कर अगले चर संरेखित होते हैं। प्रोसेसर के मूल शब्द आकार से बड़ा एक चर के लिए एक अद्यतन कभी परमाणु नहीं हो सकता है।

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

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

अस्थिरता सभी

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

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

बस जा रहा है परमाणु/अस्थिर धागा सुरक्षित है कि अगर सच था

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

वास्तविक कार्यक्रम अक्सर इस सिंक्रनाइज़ेशन आवश्यकता से पीड़ित होते हैं और Amdahls' law व्यवहार प्रदर्शित करते हैं। दूसरे शब्दों में, एक अतिरिक्त धागा जोड़ना वास्तव में प्रोग्राम को तेज़ नहीं बनाता है। कभी-कभी वास्तव में इसे धीमा कर देता है। इसके लिए किसी को भी बेहतर माउस-जाल मिल जाता है, नोबेल की गारंटी है, हम अभी भी प्रतीक्षा कर रहे हैं।

2

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

सामान्य नियम यह है: 'अस्थिर' थ्रेड सुरक्षित पहुंच सुनिश्चित करने के लिए पर्याप्त नहीं है। थ्रेड-साझा मूल्यों को सुरक्षित रूप से एक्सेस करने के लिए आपको कुछ प्लेटफ़ॉर्म-प्रदत्त तंत्र (आमतौर पर कुछ फ़ंक्शंस या सिंक्रनाइज़ेशन ऑब्जेक्ट्स) का उपयोग करना चाहिए।

अब, विशेष रूप से विंडोज पर, विशेष रूप से कुलपति ++ 2005+ संकलक के साथ, और विशेष रूप x86 और x64 सिस्टम, एक आदिम वस्तु (एक पूर्णांक की तरह) तक पहुँचने पर धागे की सुरक्षित बनाया जा सकता है यदि:

  1. पर 64- और 32-बिट विंडोज़, ऑब्जेक्ट 32-बिट प्रकार होना चाहिए, और इसे 32-बिट गठबंधन होना चाहिए।
  2. 64-बिट विंडोज़ पर, ऑब्जेक्ट 64-बिट प्रकार भी हो सकता है, और यह 64-बिट गठबंधन होना चाहिए।
  3. इसे अस्थिर घोषित किया जाना चाहिए।

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

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

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

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

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

संदर्भ:

32- और 64-बिट के गठबंधन प्रकार के atomicity पर ... https://msdn.microsoft.com/en-us/library/windows/desktop/ms684122%28v=vs.85%29.aspx

'अस्थिर' स्मृति बाड़ भी शामिल है ... https://msdn.microsoft.com/en-us/library/windows/desktop/ms686355%28v=vs.85%29.aspx

+0

यह एक अच्छा जवाब है, लेकिन मैंने हंस के जवाब को सही के रूप में चिह्नित किया क्योंकि यह अनिवार्य रूप से परमाणुता, अस्थिरता और थ्रेड सुरक्षा के लिए एक कैननिकल उत्तर है। मैं आपके विंडोज विनिर्देशों की बहुत सराहना करता हूं। यदि आप दोनों के बीच बक्षीस को विभाजित करने का कोई तरीका था तो मैं चाहता था। – loop