2010-04-08 9 views
5

क्या यह डेल्फी वीसीएल घटना द्वारा एक चर सेट को पढ़ने के लिए थ्रेड के लिए सुरक्षित है?क्या थ्रेड सुरक्षित रूप से वीसीएल घटनाओं द्वारा निर्धारित चर पढ़ सकते हैं?

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

CheckboxState := CheckBox1.Checked; 

किसी भी समय, एक धागा पढ़ता है कि चर

if CheckBoxState then ... 

इससे कोई फर्क नहीं पड़ता अगर धागा बूलियन में होने वाले बदलाव "याद करते हैं", क्योंकि धागा के रूप में एक पाश में चर की जाँच करता है यह अन्य चीजें करता है। तो यह अंततः राज्य परिवर्तन देखेंगे ...

क्या यह सुरक्षित है? या मुझे विशेष कोड चाहिए? गंभीर कोड कॉल आवश्यक और पर्याप्त के साथ परिवर्तनीय (धागे और मुख्य धागे में क्रमशः पढ़ने और लिखने के आसपास है?

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

मेरा प्रश्न इस जैसा है: Cross thread reading of a variable who's value is not considered important

(इसके अलावा मेरे पिछले प्रश्न से संबंधित: Using EnterCriticalSection in Thread to update VCL label)

+0

ध्यान दें कि वीसीएल कार्यक्रम वास्तव में कुछ विशेष नहीं हैं। आपका प्रश्न * किसी * * थ्रेड में * किसी * प्रकार के फ़ंक्शन से चर का उपयोग करने के लिए समान रूप से अच्छी तरह से लागू होता है। –

उत्तर

6

यह सुरक्षित है तीन कारणों से:

  • केवल एक धागा चर करने के लिए लिखता है।

  • परिवर्तनीय केवल एक बाइट है, इसलिए असंगत मूल्य पढ़ने का कोई तरीका नहीं है। इसे या तो True या False के रूप में पढ़ा जाएगा। डेल्फी boolean मानों के साथ संरेखण समस्याएं नहीं हो सकती हैं।

  • डेल्फी कंपाइलर कोई व्यापक जांच नहीं करता है कि एक चर वास्तव में लिखा गया है, और यदि नहीं, तो किसी भी कोड को "ऑप्टिमाइज़" नहीं करता है। गैर-स्थानीय चर हमेशा पढ़े जाएंगे, volatile विनिर्देशक की कोई आवश्यकता नहीं है।

कहा करने के बाद, आप बूलियन के बजाय एक integer मूल्य इस्तेमाल कर सकते हैं अगर आप इस बारे में वास्तव में अनिश्चित हैं, और चर के लिए लिखने के लिए InterlockedExchange() समारोह का उपयोग करें। यह यहां अधिक है, लेकिन यह जानने के लिए एक अच्छी तकनीक है, क्योंकि एकल मशीन शब्द के आकार के मूल्यों के लिए यह ताले की आवश्यकता को खत्म कर सकता है।

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

1

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

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

3

आपके मामले में (चेक की गई संपत्ति) एक पठन ऑपरेशन परमाणु है, इसलिए यह सुरक्षित है। यह टीटीएचड के समान है। संचित संपत्ति; सही ढंग से गठबंधन बाइट्स, शब्दों और डबलवर्ड्स के लिए सरल पढ़ने और लिखने के संचालन परमाणु हैं। अधिक जानकारी के लिए intel documentation जाँच कर सकते हैं:

अध्याय 8 - बहु-प्रोसेसर प्रबंधन

8.1.1 गारंटी परमाणु संचालन

Intel486 प्रोसेसर (और के बाद से नए प्रोसेसर) की गारंटी देता है कि बुनियादी स्मृति संचालन निम्नलिखित हमेशा atomically किया जाएगा:

  • पढ़ना या एक बाइट
  • पढ़ना लिख ​​रहे हैं या एक लेखन शब्द एक 16-बिट सीमा
  • पढ़ना पर गठबंधन या एक doubleword एक 32-बिट सीमा

पेंटियम प्रोसेसर (और नए प्रोसेसर के बाद से) पर गठबंधन लेखन गारंटी देता है कि निम्नलिखित अतिरिक्त मेमोरी संचालन हमेशा किया जाएगा बाहर atomically:

  • पढ़ना या एक quadword एक 64-बिट सीमा
  • 16-बिट uncached स्मृति स्थल के एक 32-बिट डेटा बस के भीतर फिट करने के लिए तक पहुँचता है पर गठबंधन लेखन
संबंधित मुद्दे