2016-07-20 18 views
0

クラスオブジェクト(ソケット接続を処理する)をロックし、それらのオブジェクトを処理のためにスレッドに渡す必要があります。あるスレッドでJavaのロックを解除し、別のスレッドでロック解除

public class Client{ 

    protected Socket socket; 
    ... 
    public Lock lock = new ReentrantLock(); 

} 

私は、作業を処理する単純なワーカークラスを持っています。

public class ClientWriterWorker extends Runnable{ 

    protected Client client; 
    protected String data; 

    public ClientWriterWorker(Client client, String data){ 
     this.client = client; 
     this.data = data; 
    } 

    @Override 
    public void run(){ 
     // do the processing 
     this.client.write(this.data); 
     // release the lock? 
     this.client.lock.unlock(); // does not work 
    } 

} 

私はロックされていないクライアントを取得し、ロックしてスレッドに渡すループを持っています。

Client currentClient = null; 
while(true){ 
    for(Client client : clients){ 
     if(client.lock.tryLock()){ 
      // we have the lock 
      currentClient = client; 
      break; 
     } 
    } 
    if(currentClient != null){ 
     break; 
    } 
} 
new Thread(new ClientWriterWorker(currentClient, "some data")).start(); 

別のスレッドでロックを解除することはできますか?私のデザインに欠陥がありますか?

+0

Javaがそれをやっても、ロックの原則に反する。ロックは、そのオブジェクトには関係ないスレッドによって保持されることを意味し、完了すると、他のスレッドが同じことをするオブジェクトを解放します – Jeeter

答えて

2

動作仕様ReentrantLockは、それをロックしたスレッドによってロック解除される必要があることを指定しています。このロックの実装の目的は、どのスレッドがロックしているかを追跡して何度でも再ロックできるようにすることです(リエントラント)。文書の一部を引用:このロックを解除する

public void unlock() 

試みが。

現在のスレッドがこのロックの所有者である場合、保持カウントが減少します。ホールドカウントがゼロになると、ロックが解除されます。現在のスレッドがこのロックの所有者でない場合、IllegalMonitorStateExceptionがスローされます。


あなたが任意のスレッドからロックされ、ロックを解除することができ、独自のLockクラスを実装することは間違いなく可能です。ここに1つの部分的な答えがあります:

public class MyLock implements java.util.concurrent.locks.Lock { 

    private boolean isLocked = false; 

    public synchronized void lock() throws InterruptedException { 
     while (isLocked) 
      wait(); 
     isLocked = true; 
    } 

    public synchronized void unlock() { 
     if (!isLocked) 
      throw new IllegalStateException(); 
     isLocked = false; 
     notify(); 
    }  

} 
0

なぜモニターを使用しないのですか? https://www.python.org/~jeremy/monitor.py彼らは終了した後に他のスリープスレッドをブロードキャスト/ウェイクアップする機能を持っています。

ここでは、あなたの問題を再考すべきであるようですが、私には見えたJava

0

でそれらを使用する方法について説明リンクhttp://www.csc.villanova.edu/~mdamian/threads/javamonitors.htmlです。

一般的に、あなたは何か(スレッド、接続、何でも)のプールを使用して何かが必要とされるたびに、プールプロバイダーオブジェクトへの呼び出しは、要求されたオブジェクトへの参照を提供します。そのオブジェクトは、(ロック解除メソッドを呼び出すことによって)プールに戻されるまで、全体的なアイデアは、オブジェクトが今、もっぱらプールからそれを要求したスレッドによって所有されて(とプールが得られないということですので、それ以上のロックは、必要とされませんそのオブジェクトを再度所有するスレッドによって返される前に、そのオブジェクトを再度取り出します)。

このパターンでは、典型的には、多くの場合、単純にプールオブジェクト(または専用のロックオブジェクト)に同期させることによって実現さ(プール用)単一のロックがあります。ロックとロック解除を行う唯一のメソッドはすべてプール上にあります(obtain()とrelease())。管理オブジェクト自体にはロックが含まれていません。それはこのようになりますバージョンの非常に最も簡単で

:私は実際にプールを初期化するために、すべてのコードの使用を省略し、利用可能なリソースがないことをあなたはケースを処理することができます明らかに
class MyResource { 
    // represents the managed resources 
} 

class MyPool { 
    private List<MyResource> available = new ArrayList<>(); 

    public synchronized MyResource obtain() { 
     MyResource result = available.isEmpty() 
      ? new MyResource() : available.remove(0); 
     return result; 
    } 

    public synchronized void release(MyResource resource) { 
     available.add(resource); 
    } 
} 

(例えば、新しいものを作成するのではなく、利用可能になるまで待つことによって)。

このバリエーションは、リソースクラスにプールへの参照を与え、release()メソッドをリソースクラスに移動することです。プール上の非公開メソッドを呼び出して実際のリリースを行います。

少しの努力で、このパターンのロックフリーバージョンは、AtomicReferenceのcompareAndSet()メソッドを使用して実装でき、どこでも同期しなくてもプールの内容を管理できます。

関連する問題