लॉक ऑब्जेक्ट को स्थिर क्यों होना पड़ता है?


112

मल्टी थ्रेडिंग में लॉकिंग के लिए निजी स्टेटिक रीडऑनली ऑब्जेक्ट का उपयोग करना बहुत आम है। मैं समझता हूं कि निजी एनकैप्सुलेशन को कसने से लॉकिंग ऑब्जेक्ट में प्रवेश के बिंदुओं को कम कर देता है और इसलिए सबसे आवश्यक है।

लेकिन स्थिर क्यों?

private static readonly object Locker = new object();

अंत में फ़ील्ड केवल मेरी कक्षा के भीतर ही उपयोग की जाती है, और मैं इसके बजाय केवल इसका उपयोग कर सकता हूं:

private readonly object Locker = new object();

कोई टिप्पणी?

अपडेट करें:

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

private readonly object Locker = new object();

और यहाँ कोड है:

    private int _priceA;
    private int _priceB;
    private EventWaitHandle[] _waithandle;
    private readonly IService _service;

//ctor
public ModuleAViewModel(IService service)
    {
        _service = service;
        _modelA = new ModelA();
        _waithandle = new ManualResetEvent[2];
        _waithandle[0] = new ManualResetEvent(false);
        _waithandle[1] = new ManualResetEvent(false);
        LoadDataByThread();
    }


 private void LoadDataByThread()
        {
            new Thread(() =>
                           {
                               new Thread(() =>
                               {
                                   lock (Locker)
                                   {
                                       _priceA = _service.GetPriceA();
                                   }
                                   _waithandle[0].Set();
                               }).Start();

                               new Thread(() =>
                               {
                                   lock (Locker)
                                   {
                                       _priceB = _service.GetPriceB();
                                   }
                                   _waithandle[1].Set();
                               }).Start();

                               WaitHandle.WaitAll(_waithandle);
                               PriceA = _priceA;
                               PriceB = _priceB;
                           }).Start();
        }

धन्यवाद


15
मेरे ज्ञान के लिए, आमतौर पर इसका इस्तेमाल उदाहरण-अज्ञेय बनाने के लिए किया जाता है। यदि "MyWorkerClass" के कई उदाहरण मौजूद हैं, तो केवल एक ही समय में दिए गए डेटा के साथ चल सकता है (यह मानते हुए कि वे सभी साझा संसाधनों का उपयोग करते हैं)।
ब्रैड क्रिस्टी

2
संपादन में एक महत्वपूर्ण विवरण का अभाव है: कहां _serviceऔर _waithandleस्थित हैं? उदाहरण? स्थिर? अन्य? यही कारण है कि हो सकता है , उदाहरण के लिए, ... एक दूरस्थ सर्वर से जान-बूझकर सिंक्रनाइज़ करने का उपयोग कर सकते हो
मार्क Gravell

दाईं ओर, दूसरे संपादन के साथ: हां, चीजों के इस छोर से आप प्रति उदाहरण लॉक कर सकते हैं। वहाँ हो सकता है यदि मूल देव (के रूप में उल्लेख) चाहता था सिंक्रनाइज़ उपयोग करने के लिए इतना है कि सर्वर केवल इस AppDomain से एक बार में एक अनुरोध हो जाता है ... मुझे लगता है कि मामला है या नहीं पता नहीं कर सकते हैं - यह स्थिर है, हालांकि बनाने के लिए कारणों के लिए किया गया है , या क्या यह सिर्फ आकस्मिक था।
मार्क Gravell

जवाबों:


177

"मल्टी थ्रेडिंग में लॉकिंग के लिए निजी स्टेटिकली ऑब्जेक्ट का उपयोग करना बहुत आम नहीं है" - बल्कि, उचित / चुने हुए ग्रैन्युलैरिटी पर लॉक का उपयोग करना आम है । कभी-कभी ऐसा होता है static। अधिक बार, IMO, यह नहीं है - लेकिन उदाहरण आधारित है।

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

तो यह वास्तव में निर्भर करता है: Lockerआपके परिदृश्य में कैसे उपयोग किया जाता है? क्या यह किसी ऐसी चीज़ की रक्षा कर रहा है जो स्वयं स्थिर है यदि ऐसा है, तो लॉक स्थिर होना चाहिए। यदि यह कुछ ऐसी चीज़ों की सुरक्षा कर रहा है जो उदाहरण आधारित है, तो IMO लॉक भी आवृत्ति आधारित होना चाहिए ।


24
क्या आप वैश्विक डेटा लोडिंग को बेहतर तरीके से अधिक विस्तार दे सकते हैं?
bizi

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

82

यह स्थिर होना जरूरी नहीं है, वास्तव में कभी-कभी इसे स्थिर नहीं होना चाहिए ।

चर को उसी स्कोप में रहना चाहिए, जहाँ आप इसे लॉकिंग के लिए उपयोग करते हैं। यदि विधियाँ स्थिर हैं, तो चर स्थिर होना चाहिए, और यदि विधियाँ उदाहरण विधियाँ हैं, तो चर का एक उदाहरण होना चाहिए।

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


28
"ए-हा" के लिए +1 ... आप सभी तरीकों को सभी उदाहरणों में बंद कर देंगे, न कि केवल तरीकों को एक ही उदाहरण में।
राडारबॉब

3
@radarbob - लघु विवरण: आप उन सभी तरीकों को लॉक नहीं करेंगे, जिन्हें आप केवल एक लॉक लेते हैं, जिसमें अधिक ग्राहक रुचि ले सकते हैं। तरीके कभी भी लॉक नहीं होते हैं, यह सिर्फ इतना है कि म्यूटेक्स लिया गया है।
अर्नो

मुझे संदेह है कि इस उत्तर को टाल देने से यह भ्रामक हो सकता है - ताला लगाने के लिए तरीकों के दायरे के साथ कुछ भी नहीं करना चाहिए - यह केवल उन तरीकों में एक्सेस किए गए साझा डेटा के दायरे से संबंधित होना चाहिए । उदाहरण विधि किसी भी साझा किए गए डेटा तक नहीं पहुंच सकती है (और इसलिए लॉकिंग की कोई आवश्यकता नहीं है), स्थिर साझा डेटा तक पहुंच सकता है (और इसलिए स्थैतिक लॉक की आवश्यकता होती है, इसके बजाय अच्छा विचार हो सकता है), स्थैतिक के लिए एक ही ...
अलेक्सी लेवेनकोव

@AlexeiLevenkov: आप सही हैं कि स्कोप वास्तव में यह तय करना चाहिए कि डेटा स्थिर है या नहीं, लेकिन तरीकों का दायरा भी उसी के अनुसार तय किया जाना चाहिए, इसलिए यह सब एक साथ फिट बैठता है। इंस्टेंस डेटा को आमतौर पर लॉकिंग की आवश्यकता नहीं होती है, लेकिन यदि थ्रेड्स के बीच इंस्टेंस साझा किया जाता है, तो आपको लॉकिंग की आवश्यकता होगी।
गुफ्फा

28

लॉक लॉक का दायरा और जीवनकाल उस 'चीज़' पर निर्भर होना चाहिए जिसे आप लॉक करना चाहते हैं। स्थैतिक ताले ज्यादातर स्थिर चीजों को लॉक करने के लिए उपयोग किए जाते हैं।


3
माइनर डिटेल: लॉक स्टैटिक नहीं है, लॉक को पहचानने के लिए आप जिस ऑब्जेक्ट का इस्तेमाल करते हैं वह स्टैटिक है। एक और मामूली विस्तार: आप "चीजों" को लॉक नहीं करते हैं।
गुफ़ा

2
हां, मुझे लगता है कि अगर हमने गलत "चीजों" को बंद करने की कोशिश की, तो वे बहुत बड़े और मजबूत हो सकते हैं, और एक दिन बच सकते हैं।
ProfK

12
@ गफ्फा यह अजीब है, ऊपर एक टिप्पणी में आपने ठीक कहा: "आप सिर्फ चीजों को ओवरकॉम्प्लिकेट कर रहे हैं," अब मैं यह कहने से पहले 1 मिनट देखता हूं, ऐसा लगता है कि आप चीजों को ओवरकंप्लीकेट कर रहे हैं :)
निकोलस पीटरसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.