2012-12-07 9 views
5

AbstractQueuedSynchronizerを使用する単純なクラスを作成しました。 「ゲート」を表すクラスを作成しました。これは開いている場合は渡すことができ、閉じている場合はブロックします。ここでは、コードです:パス方式のスレッドブロックはゲートが閉じられ、他のいくつかのスレッドがその間にゲートが開きますので、場合AbstractQueuedSynchronizer.acquireSharedは、待機状態が変更されても無限に待機します。

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); 
    } 

}; 

残念ながら、ブロックされた1が中断されません - それはブロックを無限に。ここ がそれを示してテストです:

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(); 
    } 
} 

助けてください、私はゲート通過スレッドが正常にロックを獲得するために何を変更する必要があります。

+0

を使用してprotected try*()方法であなたのロックポリシーを定義し、私はあなたが同期を呼び出す必要があるとします。あなたがゲートを開くと、releaseShared(1) – hoaz

答えて

2

setState()は状態を変更するだけですが、ブロックされたスレッドには変更を通知しません。

  • クライアントがpublic取得/解放方法

  • を呼び出す:代わりに

    したがって、あなたが使用する必要があります取得/解除方法:次のように

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

    だから、AbstractQueuedSynchronizerのワークフロー全体が見えますこれらのメソッドはすべての同期機能を整理し、実際のロックポリシーをに委任しますの方法

  • あなたはあなたの実装では、AbstractQueuedSynchronizerのJava-docに提供BooleanLatch、と非常によく似ていますgetState()/setState()/compareAndSetState()

関連する問題