यदि कोई एक सिंक्रनाइज़ (यह) का उपयोग कर सकता है तो एक रेन्ट्रेंटलॉक का उपयोग क्यों करें?


317

मैं यह समझने की कोशिश कर रहा हूं कि यदि कोई उपयोग कर सकता है तो क्या संगोष्ठी में ताला महत्वपूर्ण है synchronized (this)। नीचे डमी कोड में, मैं या तो कर सकता हूं:

  1. संपूर्ण विधि को सिंक्रनाइज़ करें या असुरक्षित क्षेत्र को सिंक्रनाइज़ करें ( synchronized(this){...})
  2. या रेन्ट्रेंटलॉक के साथ असुरक्षित कोड क्षेत्र को लॉक करें।

कोड:

    private final ReentrantLock lock = new ReentrantLock(); 
    private static List<Integer> ints;

    public Integer getResult(String name) { 
        .
        .
        .
        lock.lock();
        try {
            if (ints.size()==3) {
                ints=null;
                return -9;
            }   

            for (int x=0; x<ints.size(); x++) {
                System.out.println("["+name+"] "+x+"/"+ints.size()+". values >>>>"+ints.get(x));
            }

        } finally {
            lock.unlock();
        } 
        return random;
}

1
BTW सभी जावा आंतरिक ताले स्वभाव से प्रतिरूप हैं।
अनिकेत ठाकुर

@ पोंगापुंडित इसलिए synchronized(this){synchronized(this){//some code}}डेड लॉक नहीं होगा। आंतरिक ताला के लिए अगर वे एक संसाधन पर निगरानी प्राप्त करते हैं और यदि वे इसे फिर से चाहते हैं तो वे इसे एक मृत ताला के बिना प्राप्त कर सकते हैं।
अनिकेत ठाकुर

जवाबों:


474

एक ReentrantLock है असंरचित , के विपरीत synchronizedनिर्माणों - यानी आप और लॉक करने के लिए एक ब्लॉक संरचना का उपयोग करने की जरूरत नहीं है यहां तक कि तरीकों भर में एक ताला पकड़ कर सकते हैं। एक उदाहरण:

private ReentrantLock lock;

public void foo() {
  ...
  lock.lock();
  ...
}

public void bar() {
  ...
  lock.unlock();
  ...
}

एक synchronizedनिर्माण में एकल मॉनिटर के माध्यम से इस तरह के प्रवाह का प्रतिनिधित्व करना असंभव है ।


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

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


ReentrantLock हो सकता है यह भी हो सकता है और अधिक विश्वसनीय , उच्च विवाद के तहत काफी बेहतर प्रदर्शन करते हुए। आप इसके बारे में और अधिक यहाँ पढ़ सकते हैं ।

हालाँकि, यह दावा किया गया है; निम्नलिखित टिप्पणी देखें:

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


आपको कब उपयोग करना चाहिए ReentrantLock? उस developerWorks लेख के अनुसार ...

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


26
Lycog.com के लिंक को 'अधिक स्केलेबल होने के लिए जाना जाता है' को हटाया जाना चाहिए। रेंटेंट लॉक टेस्ट में, हर बार एक नया लॉक बनाया जाता है, इस प्रकार कोई विशेष लॉकिंग नहीं होती है और परिणामी डेटा अमान्य होता है। इसके अलावा, आईबीएम लिंक अंतर्निहित बेंचमार्क के लिए कोई स्रोत कोड प्रदान नहीं करता है ताकि इसकी जांच करना असंभव हो कि क्या परीक्षण भी सही तरीके से आयोजित किया गया था। व्यक्तिगत रूप से, मैं केवल स्केलेबिलिटी के बारे में पूरी लाइन हटा दूंगा, क्योंकि पूरा दावा अनिवार्य रूप से असमर्थित है।
देव

2
मैंने आपकी प्रतिक्रिया के आलोक में पोस्ट को संशोधित किया।
वृद्धिन

6
यदि प्रदर्शन आपके लिए एक उच्च चिंता का विषय है, तो ऐसे तरीके की तलाश करना न भूलें, जहाँ आपको सं सिंक्रनाइज़ेशन की आवश्यकता हो।
mcoolive

2
प्रदर्शन की बात मेरे लिए बिल्कुल भी मायने नहीं रखती है। यदि रिअंट्रेंट लॉक बेहतर प्रदर्शन करेंगे तो सिंक्रोनाइड को सिर्फ उसी तरह लागू नहीं किया जाएगा जिस तरह से एक रिअंट्रेंट लॉक इंटर्नलली?
तैबी

2
@ user2761895 ReentrantLockPseudoRandomलाइकॉग लिंक में कोड बिल्कुल नए, अनियंत्रित ताले के हर आह्वान का उपयोग कर रहा है setSeedऔरnext
Oldrinb

14

ReentrantReadWriteLockएक विशेष लॉक है जबकि synchronized(this)एक सामान्य उद्देश्य लॉक है। वे समान हैं लेकिन काफी समान नहीं हैं।

आप सही हैं कि आप synchronized(this)इसके बजाय उपयोग कर सकते हैं ReentrantReadWriteLockलेकिन विपरीत हमेशा सच नहीं होता है।

यदि आप बेहतर ढंग से समझना चाहते हैं कि ReentrantReadWriteLockविशेष रूप से निर्माता-उपभोक्ता थ्रेड सिंक्रोनाइज़ेशन के बारे में कुछ जानकारी दी गई है।

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

वैसे, synchronized(this)सार्वजनिक वर्ग उदाहरण का उपयोग करते हुए - और सामान्य लॉकिंग में - समस्याग्रस्त हो सकता है क्योंकि यह आपके कोड को संभावित डेड-लॉक तक खोल देता है क्योंकि कोई और जानबूझकर प्रोग्राम में कहीं और आपकी वस्तु के खिलाफ लॉक करने की कोशिश नहीं कर सकता है।


संभावित मृत-तालों को रोकने के लिए क्योंकि कोई और जानबूझकर आपकी वस्तु के खिलाफ कहीं और लॉक करने की कोशिश नहीं कर सकता है, जैसे कि progame में एक निजी वस्तु उदाहरण का उपयोग सिंक्रनाइज़ेशन मॉनिटर के रूप में होता है: public class MyLock { private final Object protectedLongLockingMonitor = new Object(); private long protectedLong = 0L; public void incrementProtectedLong() { synchronized(protectedLongLockingMonitor) { protectedLong++; } } }
sushicutta

9

ReentrantLock के बारे में oracle प्रलेखन पृष्ठ से :

एक मूल पारस्परिक बहिष्कार लॉक एक ही मूल व्यवहार और शब्दार्थ के साथ है क्योंकि अंतर्निहित मॉनिटर लॉक का उपयोग सिंक्रनाइज़ तरीकों और बयानों के साथ किया जाता है, लेकिन विस्तारित क्षमताओं के साथ।

  1. एक रेन्ट्रेंटलॉक पिछले सफलतापूर्वक लॉकिंग थ्रेड के स्वामित्व में है, लेकिन अभी तक इसे अनलॉक नहीं किया गया है। एक थ्रेडिंग लॉक लॉक सफलतापूर्वक लौटेगा, जब लॉक को दूसरे थ्रेड के स्वामित्व में नहीं किया जाएगा। यदि वर्तमान थ्रेड पहले से ही लॉक का मालिक है, तो विधि तुरंत वापस आ जाएगी।

  2. इस वर्ग के लिए निर्माता एक वैकल्पिक निष्पक्षता पैरामीटर को स्वीकार करता है । जब यह सही है, तो विवाद के तहत, सबसे लंबे समय तक प्रतीक्षा करने वाले धागे तक पहुंच देने के पक्ष में है । अन्यथा यह लॉक किसी विशेष एक्सेस ऑर्डर की गारंटी नहीं देता है।

इस लेख के अनुसार ReentrantLock प्रमुख विशेषताएं

  1. बाधा डालने की क्षमता।
  2. लॉक का इंतजार करते हुए टाइमआउट करने की क्षमता।
  3. निष्पक्ष ताला बनाने की शक्ति।
  4. लॉक के लिए प्रतीक्षा धागा की सूची प्राप्त करने के लिए एपीआई।
  5. बिना अवरोध के लॉक के लिए प्रयास करने की लचीलापन।

आप आगे पढ़ने और लिखने के संचालन पर दानेदार लॉकिंग पर नियंत्रण हासिल करने के लिए ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock का उपयोग कर सकते हैं ।

बेनजामेन के विभिन्न प्रकार के रेंट्रेंटलॉक्स के उपयोग के इस लेख पर एक नज़र डालें


2

थ्रेड भुखमरी से बचने के लिए आप निष्पक्षता नीति या समयबाह्य के साथ रीटरेंट ताले का उपयोग कर सकते हैं। आप थ्रेड फेयरनेस पॉलिसी लागू कर सकते हैं। यह आपके संसाधनों के लिए हमेशा के लिए प्रतीक्षा कर रहे एक धागे से बचने में मदद करेगा।

private final ReentrantLock lock = new ReentrantLock(true);
//the param true turns on the fairness policy. 

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

इसके अलावा, अगर यह ब्लॉक से बच सकता है तो सिंक्रोनाइज़ अनिश्चित काल के लिए ब्लॉक कर सकता है। रीटरैंटलॉक में टाइमआउट सेट हो सकता है।


1

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

रेंटेंट लॉक्स बहुत अधिक लचीले होते हैं और उनकी निष्पक्षता नीति होती है जिसमें यदि कोई थ्रेड लंबे समय तक प्रतीक्षा कर रहा है और वर्तमान में निष्पादित थ्रेड के पूरा होने के बाद हम यह सुनिश्चित कर सकते हैं कि लंबे समय तक प्रतीक्षा थ्रेड को साझा किए गए संसाधन तक पहुंचने का मौका मिल रहा है प्रणाली के थ्रूपुट और अधिक समय लेने वाली है।


1

मान लें कि यह कोड एक थ्रेड में चल रहा है:

private static ReentrantLock lock = new ReentrantLock();

void accessResource() {
    lock.lock();
    if( checkSomeCondition() ) {
        accessResource();
    }
    lock.unlock();
}

क्योंकि थ्रेड लॉक का मालिक है, इसलिए यह कई कॉल्स को लॉक करने की अनुमति देगा (), इसलिए यह लॉक को फिर से दर्ज करता है। यह एक संदर्भ गणना के साथ प्राप्त किया जा सकता है ताकि इसे फिर से लॉक का अधिग्रहण न करना पड़े।


0

एक बात ध्यान में रखना है:

' रेंट्रेंटलॉक ' नाम अन्य लॉकिंग तंत्र के बारे में एक गलत संदेश देता है कि वे फिर से प्रवेश नहीं कर रहे हैं। यह सच नहीं है। 'सिंक्रनाइज़' के माध्यम से अधिग्रहीत लॉक भी जावा में फिर से प्रवेश करता है।

मुख्य अंतर यह है कि लॉक सिंक नहीं होने पर 'सिंक्रोनाइज़' में आंतरिक लॉक (प्रत्येक ऑब्जेक्ट में एक) का उपयोग किया जाता है।


0

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.