2012-04-25 20 views
9

मेरे पास एक थ्रेड है जो स्पिन करता है जब तक कि किसी अन्य थ्रेड द्वारा एक int बदल नहीं जाता है।क्या मुझे इस क्षेत्र को अस्थिर होने की आवश्यकता है?

int cur = this.m_cur; 
while (cur > this.Max) 
{ 
    // spin until cur is <= max 
    cur = this.m_cur; 
} 

क्या यह .m_cur को काम करने के लिए अस्थिर घोषित करने की आवश्यकता है? क्या यह संभव है कि यह संकलक अनुकूलन के कारण हमेशा के लिए स्पिन होगा?

+9

एक संपत्ति को int बनाओ और सेटर विधि में थ्रेड, (autoResetEvent, शायद) को सिग्नल करें। समस्या बाईपास, सीपीयू उपयोग कम, अस्थिर संदेह हटा दिया। –

+0

यह कुछ दुर्लभ मामलों को छोड़कर आम तौर पर एक बुरा विचार है; क्या आपको पता चलेगा कि कितने माइक्रोसॉन्ड अधिकतम आप स्पिन करने की उम्मीद करते हैं? –

+0

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

उत्तर

12

हाँ, यह एक कठिन आवश्यकता है। बस-इन-टाइम कंपाइलर को प्रोसेसर रजिस्टर में m_cur के मान को स्मृति से रीफ्रेश किए बिना स्टोर करने की अनुमति है। वास्तव में x86 जिटर करता है, x64 जिटर नहीं करता है (कम से कम आखिरी बार मैंने इसे देखा)।

अस्थिर कीवर्ड को इस अनुकूलन को दबाने के लिए आवश्यक है।

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

+4

मुझे यह पसंद है कि आपने अपने प्रश्न का उत्तर कैसे दिया, बस इतना करना कि 'ऐसा करने का एक और तरीका' कहें। उनकी जरूरतों के आधार पर एक संकेत कहीं अधिक कुशल हो सकता है, लेकिन उनका सवाल "... या बेहतर क्या है?" साथ ही, मुझे यकीन है कि कई प्रयोगों ने यहां कुछ नया सीखा है। धन्यवाद। – payo

+0

+1: वैसे, क्या हम निश्चित हैं कि गुण जेआईटी कंपाइलर को उठाने अनुकूलन करने से रोकते हैं। संपत्ति सरल होगी इसलिए इसे पहले रेखांकित किया जाएगा। मुझे लगता है कि 2 चरण अनुकूलन करना संभव है: इनलाइन-लिफ्ट। मैंने चश्मे में कुछ भी नहीं देखा है जो इसे रोक देगा, लेकिन हो सकता है कि मैंने इसे कठिन नहीं देखा। –

+1

@ ब्रायन - मैंने उन मामलों में उपयोग की जाने वाली संपत्तियों के बारे में परेशान होने के कारण इसे खोजा जहां अस्थिरता की आवश्यकता होगी लेकिन बिना किसी सिंक्रनाइज़ेशन के। BackgroundWorker.CancellationPending एक अच्छा उदाहरण है, एक बूल। यह कहीं भी वर्णित नहीं है, मुझे पता है, * अस्थिर * के अर्थशास्त्र बहुत खराब दस्तावेज हैं। वे हमेशा .NET से पहले भी रहे हैं। –

4

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

http://igoro.com/archive/volatile-keyword-in-c-memory-model-explained/

नीचे

class Test 
{ 
    private bool _loop = true; 

    public static void Main() 
    { 
     Test test1 = new Test(); 

     // Set _loop to false on another thread 
     new Thread(() => { test1._loop = false;}).Start(); 

     // Poll the _loop field until it is set to false 
     while (test1._loop == true) ; 

     // The loop above will never terminate! 
    } 
} 

ब्लॉग से

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

+1

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

+0

सच है। हालांकि मुझे लगता है कि लॉक स्पिन करने के कारण भी हैं, जैसे थ्रेड देने के संदर्भ स्विच से बचें। –

+0

संदर्भ-स्विच को एविड करने की समस्या यह है कि यह हमेशा आसानी से संभव नहीं होता है। इसके अलावा, ओपी कोड एक क्लैसिक बुलीयन-फ्लैग स्पिनलॉक नहीं है। यदि बॉक्स ओवरलोड हो गया है क्योंकि कोर की तुलना में अधिक तैयार धागे हैं, तो मतदान थ्रेड को छूट दी जा सकती है और थोड़ी देर तक नहीं चल सकती है। इस समय के दौरान, यह 'cur' सीमा से बाहर जाने का पता नहीं लगा सकता है। यदि कर्सर चलने से पहले सीमा के भीतर वापस आता है, तो सीमा से बाहर की स्थिति पूरी तरह से चूक गई है। –

0

यह इस बात पर निर्भर करता है कि m_cur को कैसे संशोधित किया जा रहा है। यदि यह m_cur--; जैसे सामान्य असाइनमेंट स्टेटमेंट का उपयोग कर रहा है, तो इसे अस्थिर होने की आवश्यकता है। हालांकि, अगर इसे Interlocked परिचालनों में से किसी एक का उपयोग करके संशोधित किया जा रहा है, तो ऐसा इसलिए नहीं है क्योंकि इंटरलॉक की विधियां स्वचालित रूप से मेमोरी बाधा डालती हैं ताकि यह सुनिश्चित किया जा सके कि सभी धागे ज्ञापन प्राप्त करें।

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

उसने कहा, जैसे कि अन्य ने कहा है कि मतदान लूप भारी रूप से अपर्याप्त हैं। थ्रेड को रोकने के लिए बेहतर होगा जो इंतजार करने की ज़रूरत है, और जो कोई भी m_cur को संशोधित कर रहा है उसे समय आने पर इसे जागने का प्रभार लेना चाहिए। Monitor.Wait() and Monitor.Pulse() और AutoResetEvent दोनों आपकी विशिष्ट आवश्यकताओं के आधार पर कार्य के लिए उपयुक्त हो सकते हैं।

+0

मतदान लूप समाधान कम से कम एक ओवरलोडेड बॉक्स पर नहीं, वैसे भी विश्वसनीय रूप से काम नहीं करता है। जब काउंटर नहीं चल रहा है तो सेटर थ्रेड एक ऑफ-ऑफ-रेंज 'कर' लिख सकता है। यदि परामर्शदाता चलाने से पहले 'cur' फिर से श्रेणी में वापस आ जाता है, तो ऑफ-ऑफ-रेंज की स्थिति बिल्कुल नहीं मिली है। –

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