5

synchronizedの機能と の機能を組み合わせる方法を探していjava.util.concurrent.locks.ReentrantReadWriteLockます。より具体的には、WriteLockが設定されている場合にのみ 1 つのメソッドをロックしたいのですが、 のようなオブジェクト変数にロックを設定したいと考えていますsynchronized。説明に役立つ例を次に示します。

ReentrantReadWriteLock の例

public void methodOne(String var) {
    lock.writeLock().lock;
    try {
        // Processing
    }
    finally {
        lock.writeLock().unlock();
    }
}

public void methodTwo(String var) {
    lock.readLock().lock;
    try {
        // Processing
    }
    finally {
        lock.readLock().unlock();
    }
}

この例では、 onがロックされていないmethodTwo限り、ブロックせずに呼び出すことができます。これは良い機能であり、私が探している機能ですが、がロックされている場合、 のすべてのケースでロックされています。代わりに、次のようにロックするだけにしたいと思います:writeLockmethodOnewriteLockvarvarsynchronized

同期の例

public void methodOne(String var) {
    synchronized(var) {
        // Processing
    }
}

public void methodTwo(String var) {
    synchronized(var) {
        // Processing
    }
}

現在、メソッドは入力の条件付きのみをブロックします。これは良いことであり、私が探しているものですがmethodTwo、同じキーで複数の同時呼び出しがある場合、それらはブロックされます。代わりに、これを「読み取り」スタイルのロックにして、呼び出しを許可したいと思います。

基本的に、両方の機能セットを取得するために変数に同期できる ReadWriteLock が必要です。

4

3 に答える 3

5

基本的に、両方の機能セットを取得するために変数に同期できる ReadWriteLock が必要です。

まず、異なる値の数によっては、膨大な数のロックが作成される可能性があります。代わりに、更新を少数に分割できるように、ある種の分類などを検討することもできます。たとえば、さまざまな var 値を細分化する方法はありますか。いろいろな価値観があるのではないでしょうか?値の固定数が少ない場合、これは問題になりません。

ある種のコレクションを構築する必要がありReentrantReadWriteLockます。おそらく、ConcurrentHashMapすべてのロックを格納する a を使用します。

Map<String, ReadWriteLock> lockMap =
    new ConcurrentHashMap<String, ReadWriteLock>():
...
public void writeProcessing(String var) {
    lock = lockMap.get(var);
    lock.writeLock().lock;
    try {
       // Processing
    } finally {
       lock.writeLock().unlock();
    }
}

事前に異なる値を登録する必要があります。または、オンデマンドで作成することもできます。繰り返しますが、これは法外な数のロックを作成する可能性があります。

public void writeProcessing(String var) {
    lock = getLockForVar(var);
    ...
}

private ReadWriteLock getLockForVar(String var) {
   ReadWriteLock lock = lockMap.get(var);
    if (lock != null) {
        return lock;
    }
    // this might create an extra lock because of race conditions...
    lock = new ReadWriteLock();
    ReadWriteLock current = lockMap.putIfAbsent(var, lock);
    if (current == null) {
        return lock;
    } else {
        return current;
    }
}
于 2013-10-23T21:18:35.023 に答える
0

私があなたを正しければ、次
の解決策は、オブジェクトを読み取るときにオブジェクトを同期しないこと、および書き込むときにその逆の解決策に役立つと思います。

public void methodOne(String var) {
    synchronized(var) {
        // Processing the writting
    }
}

public void methodTwo(String var) {
        // Processing the reading
}

また、何かを直接変更 ( , など) として更新する

場合の変数 (存在する場合) の更新方法について言及させてください。そのため、ブロックを省略し、変数をvolatileとしてマークするだけで、変数を作成します。揮発性は読み取り変更更新のロックをカバーしていないため(のような)methodonea=12name="IBM"synchronizeda++

編集:さて、あなたがケーキを食べたり食べたりするつもりなら、私が助けるかもしれないと思うことは、何か他のもの(実際の変数よりも、考えるpthread)で同期するbooleanことです。このような

private volatile boolean methodOneRunning=false;
private Object readLock=new Object(),writeLock=new Object();
public void methodOne(String var) {
    synchronized(writeObject) {
        methodOneRunning=true;
        // Processing the eating
        methodOneRunning=false;
    }
}

public void methodTwo(String var) {
        if(methodOneRunning){
           synchronized(readLock){
             //having the cake
           }
        }else{
             //when thread one is not running!
        }
}

これは、メソッド 2 がその時点で読み取りを開始し0
、スレッド 1 がその時点でメソッド 2 が入力された後にそのジョブを終了する可能性1
があるため、ここではスレッド 2 がロックを使用して変数を読み取ります... したがって、これは監視する別のスレッドによって解決される可能性がありますスレッド 1 のアクティビティを終了し、終了/終了状態についてスレッド 2 に通知します。

于 2013-10-23T21:15:37.073 に答える