SORU
21 Ocak 2009, ÇARŞAMBA


Güvenli bir şekilde elde etmek için nasıl Java ReentrantReadWriteLocks - yazma kilidi?

Şu anda benim kod bir ReentrantReadWriteLock ağaç gibi bir yapı üzerinden erişimi eşitlemek için kullanıyorum. Bu yapı büyük ve zinde olmam çok küçük parçalar için zaman zaman değişiklikler ile çok iş parçacığı tarafından aynı anda okuma - okuma-yazma deyim. Bu özel sınıf bir okuma kilidi kilit yazmak yükseltmek, Javadocs başına bir yazma kilidi almadan önce okuyun kilidi açmak gerekir, böylece anlıyorum. Olmayan desteklemeyeceğini bağlamlarda bu model başarılı bir şekilde daha önce de kullandım.

Ancak buluyorum ne güvenilir bir yazma kilidi sonsuza kadar engelleme olmadan elde edemem. Okuma beri kilit desteklemeyeceğini ve aslında gibi, basit bir kod kullanıyorum

lock.getReadLock().unlock();
lock.getWriteLock().lock()

eğer readlock reentrantly elde varsa engelleyebilirsiniz. Her çağrı dakika sayısını azaltır kilidini açmak ve kilidi sadece tutun sayım sıfıra ulaştığında aslında serbest bırakılır.

EDİTbunu netleştirmek için, sanmıyorum açıkladım çok iyi başlangıçta - farkındayım Yok Dahili kilit yükseltme bu sınıf, ve ben sadece serbest okuma kilit ve elde yazma kilidi. Benim sorunum/diğer iş ne olursa olsun, getReadLock().unlock() arama aslında serbest değilbubu durumda getWriteLock().lock() çağrı sonsuza kadar bu konu gibi engeller eğer reentrantly satın aldı eğer kilidi, az iş var hala okuma kilidi ve böylece bloklar kendisi üzerinde bir etkisi var.

Örneğin, bu kod parçacığı hiçbir zaman çalıştırma kilidi erişim: başka bir iş parçacığı ile tek-iş parçacığına sahip bile sertifika deyimi, ulaşacak

final ReadWriteLock lock = new ReentrantReadWriteLock();
lock.getReadLock().lock();

// In real code we would go call other methods that end up calling back and
// thus locking again
lock.getReadLock().lock();

// Now we do some stuff and realise we need to write so try to escalate the
// lock as per the Javadocs and the above description
lock.getReadLock().unlock(); // Does not actually release the lock
lock.getWriteLock().lock();  // Blocks as some thread (this one!) holds read lock

System.out.println("Will never get here");

Soruyorum, bu durumun üstesinden gelmek için güzel bir deyim var mı? Özellikle, ne zaman bir iş parçacığı içeren bir okuma kilidi (muhtemelen reentrantly) keşfeder yapması gereken bazı yazma ve böylece istediği için "askıya alma" kendi okuma kilidi sipariş almaya yazma kilidi (engelleme gibi gerekli diğer konuları kendi çıkış tutar okuma kilidi), ve sonra "Aç" bekle okuma kilit aynı durumu sonra?

Bu ReadWriteLock uygulama özellikle desteklemeyeceğini olacak şekilde tasarlanmıştır beri, mutlaka bir kilit kilitler reentrantly elde edilebilir ne zaman yazmak için bir okuma kilidi yükseltmek için daha makul bir yolu var mı? Bu naif bir yaklaşım çalışmıyor demektir kritik bir parçasıdır.

CEVAP
21 Ocak 2009, ÇARŞAMBA


Bu konuda biraz ilerleme var. Açıkça kilit değişken sadece bir ReadWriteLock (ideal daha az, ama muhtemelen bu durumda gerekli bir kötülük) yerine bir ReentrantReadWriteLock olarak ilan ederek getReadHoldCount() yöntem diyebilirim. Bu benim için geçerli iş parçacığı tutan sayısını elde etmek izin verir, ve böylece readlock bu birçok kez (ve aynı sayıda sonra yeniden almak) de bırakabilirim. Bu hızlı ve kirli bir testi ile gösterildiği gibi çalışır, bu yüzden:

final int holdCount = lock.getReadHoldCount();
for (int i = 0; i < holdCount; i  )
{
   lock.getReadLock().unlock;
}
lock.getWriteLock().lock()
try
{
   // Perform modifications
}
finally
{
   // Downgrade by reacquiring read lock before releasing write lock
   for (int i = 0; i < holdCount; i  )
   {
      lock.getReadLock().lock();
   }
   lock.getWriteLock().unlock();
}

Yine de, bu yapabileceğim en iyi şey olacak mı? Ve hala daha az "" moda. kılavuzda bunun üstesinden gelmenin bir yolu var umuyorum ki çok zarif gelmiyor

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Bad Lip Reading

    Bad Lip Read

    22 Mart 2011
  • cosmicrocketman

    cosmicrocket

    17 NİSAN 2006
  • ELPRESADOR

    ELPRESADOR

    21 HAZİRAN 2008