2012-12-07 12 views
5

AbstractQueuedSynchronizer'ı kullanan basit bir sınıf yazdım. "Geçit" i temsil eden bir sınıf yazdım, eğer açıksa ya da kapanırsa engellenebilir. İşte kod: geçişli yöntemine bir iplik blokları kapısı kapatıldı ve bazı diğer iplik arada kapıyı açar, çünkü eğerAbstractQueuedSynchronizer.acquireShared, bekleme koşulunun değişmesi durumunda bile sonsuza kadar bekler

public class GateBlocking { 

    final class Sync extends AbstractQueuedSynchronizer { 
    public Sync() { 
     setState(0); 
    } 

    @Override 
    protected int tryAcquireShared(int ignored) { 
     return getState() == 1 ? 1 : -1; 
    } 

    public void reset(int newState) { 
     setState(newState); 
    } 
    }; 

    private Sync sync = new Sync(); 

    public void open() { 
    sync.reset(1); 
    } 

    public void close() { 
    sync.reset(0); 
    } 

public void pass() throws InterruptedException { 
    sync.acquireShared(1); 
    } 

}; 

yazık ki, bloke bir kesintiye almaz - Bu bloklar sonsuz.

public class GateBlockingTest { 

    @Test 
    public void parallelPassClosedAndOpenGate() throws Exception{ 
     final GateBlocking g = new GateBlocking(); 
     Thread t = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        Thread.sleep(2000); 
        g.open(); 
       } catch (InterruptedException e) { 
       } 
      } 
     }); 


     t.start(); 
     g.pass(); 
    } 
} 

Lütfen yardım edin, ben kapı geçen ipliği başarıyla kilidi almak yapmaya değiştirmek gerektiğini: İşte gösteren bir testtir.

+0

Uygulamanız AbstractQueuedSynchronizer Java Doc sağlanan BooleanLatch, çok benzer kullanarak protected try*() yöntemlerde sizin kilitleme ilkesini tanımlayan, sana senkronizasyonu çağırmanız gerekir herhalde. openShip (1) kapıları açtığınızda – hoaz

cevap

2

setState() gibi görünüyor, yalnızca durumu değiştirir, ancak değişiklik hakkında engellenen konulara uyarı vermez.

  • Müşteriler public acquire/bırakma yöntemleri

  • çağrı: yerine

    nedenle kullanmanız gereken acquire/bırakma yöntemleri: aşağıdaki gibi

    @Override 
    protected boolean tryReleaseShared(int ignored) { 
        setState(1); 
        return true; 
    } 
    ... 
    public void open() { 
        sync.releaseShared(1); 
    } 
    

    Yani, AbstractQueuedSynchronizer genel iş akışı görünüyor Bu yöntemler tüm senkronizasyon işlevlerini düzenler ve gerçek kilitleme politikasını'e aktarıryöntemleri

  • Sen getState()/setState()/compareAndSetState()

İlgili konular