2015-10-26 4 views
9

ReadWriteLock ढाल (उदाहरण से tryLock() नीचे हमेशा true रिटर्न) ReentrantReadWriteLock कार्यान्वयन द्वारा अनुमति दी है:ReadWriteLock अपग्रेड क्यों नहीं है?

void downgrade(final ReadWriteLock readWriteLock) { 
    boolean downgraded = false; 
    readWriteLock.writeLock().lock(); 
    try { 
     // Always true, as we already hold a W lock. 
     final boolean readLockAcquired = readWriteLock.readLock().tryLock(); 
     if (readLockAcquired) { 
      // Now holding both a R and a W lock. 
      assert ((ReentrantReadWriteLock) readWriteLock).getReadHoldCount() == 1; 
      assert ((ReentrantReadWriteLock) readWriteLock).getWriteHoldCount() == 1; 

      readWriteLock.writeLock().unlock(); 
      downgraded = true; 
      try { 
       // Now do some work with only a R lock held 
      } finally { 
       readWriteLock.readLock().unlock(); 

       assert ((ReentrantReadWriteLock) readWriteLock).getReadHoldCount() == 0; 
       assert ((ReentrantReadWriteLock) readWriteLock).getWriteHoldCount() == 0; 
      } 
     } 
    } finally { 
     if (!downgraded) { 
      // Never (we were holding a W lock while trying a R lock). 
      readWriteLock.writeLock().unlock(); 
     } 
     assert ((ReentrantReadWriteLock) readWriteLock).getReadHoldCount() == 0; 
     assert ((ReentrantReadWriteLock) readWriteLock).getWriteHoldCount() == 0; 
    } 
} 

एक समान तरीके से एक ताला उन्नयन की अनुमति नहीं दे के पीछे विचार यह क्या था? एक लिखें ताला के लिए tryLock() विधि नीचे सुरक्षित रूप से अन्य धागे के अभाव में true w/oa जोखिम लौट सकते हैं एक गतिरोध के लिए एक पढ़ें ताला पकड़े:

void upgrade(final ReadWriteLock readWriteLock) { 
    readWriteLock.readLock().lock(); 
    try { 
     // Always false: lock upgrade is not allowed 
     final boolean writeLockAcquired = readWriteLock.writeLock().tryLock(); 
     // ... 
    } finally { 
     readWriteLock.readLock().unlock(); 
    } 
} 
+4

नाकाम रहे हैं आप जावा 8 का उपयोग करते हैं बनाने के लिए प्रयास करता है, आप 'StampedLock' पर एक नजर है कर सकते हैं। अधिक आम तौर पर, आप एंजेलिका लैंगर से [इस वीडियो] (https://www.youtube.com/watch?v=Q_0_1mKTlnY) पर एक नज़र डालना चाहते हैं। एक घंटी बजती है, है ना? ;) – fge

उत्तर

2

पहले, आइए कि उन्नयन और ढाल रहे हैं ध्यान दें ReadWriteLock एस के लिए अर्थात् जटिलता के मामले में समकक्ष नहीं है।

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

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

आप शायद अब तक देखते हैं, पूरी तरह से ReentrantReadWriteLock में इन समस्याओं से निपटने के रूप में कम से कम कहने के लिए असुविधाजनक है (अब भी, यह क्या नेट के ReaderWriterLock की कोशिश करता है और मुझे लगता है कि वास्तव में क्या करने के लिए सफल होता है)। मेरा अनुमान है कि final boolean writeLockAcquired = readWriteLock.writeLock().tryLock(); कुछ मामूली मामलों में सफल होने के लिए किया जा सकता था, लेकिन अपग्रेड करने योग्य अभी भी सामान्य उपयोग के लिए पर्याप्त नहीं होता - भारी पर्याप्त विवाद के तहत, यदि आप लिखने के लिए दौड़ खो देते हैं, तो आप एक ही नाव जैसे कि आपने रीड लॉक को अनलॉक किया है और लिखने के लॉक को प्राप्त करने का प्रयास किया है (किसी और के लिए चुपके के लिए मौका छोड़ना और बीच में लिखना लॉक लेना)।

लॉक अपग्रेडिबिलिटी प्रदान करने का एक अच्छा तरीका केवल एक ही थ्रेड को अपग्रेड करने का प्रयास करना है - यह ReentrantReadWriteUpdateLock करता है या क्या .NET के ReaderWriterLockSlim करता है। हालांकि मैं अभी भी सिफारिश करेंगे जावा 8 के StampedLock के रूप में:

    कम विवाद अपने आशावादी पढ़ता तहत
  • ताले को पढ़ने का उपयोग करने से बहुत तेजी से कर रहे हैं
  • अपने एपीआई है अब तक कम (आशावादी पढ़ने से उन्नयन ताला लिखने के लिए ताला पढ़ने के बारे में प्रतिबंधात्मक)
  • मेरी विभिन्न एक यथार्थवादी JMH बेंचमार्क जहां अन्य इसी तरह के ताले में से एक धड़कता है यह लगभग हमेशा
संबंधित मुद्दे