0

はい、同期ロック構文はブロック構造であるため簡単ですが、使用できない場合があります。「同期」の以前の使用法と互換性があるように、オブジェクトの「同期」モニターを明示的にロックおよびロック解除する方法はありますか?

class MyObj {
    Object locker_ = new Object();
    void lockedMethod() {
       synchronized(locker_) {
           ....
       }
    }
    Iterator lockTraversal() {
        explicitlyWaitForAndAcquireLock(locker_); // assume will not throw exception
        return(getAnIterator());
    }
    void unlockTraversal() {
        explicitlyReleaselock(locker_);
    }
}


 MyObj obj = (...)

 try {
     Iterator it = obj.lockTraversal();
     for(;;) // iterate 
 } finally {
     obj.unlockTraversal();
 }

もちろん、この例では、「クロージャー」はこの必要性を排除します。「スタック スコープ」デストラクタと同様に;^>

4

5 に答える 5

1

JVM ベリファイアは、ロックとアンロックのバランスを取る必要があるように設計されています。したがって、明示的にロックとロック解除をペアにすることはできません。

再入可能な動作に依存していない限り、別のスレッドでロックを保持できます (これは常に悪い考えのように思えます)。スレッドセーフな方法で他のスレッドと通信することで、関連する事前発生関係を確実に取得できます。

目標を達成するための標準的な方法は、javax.swing.text.AbstractDocument.renderで使用されるExecute Around イディオムです。

Java SE 7 以前 (1.0* ではない) では、Execute Around は次のようになります。

public interface Traversal<T>() {
    void traverse(Iterator<T> iter);
}
public class MyObj {
    private final Object lock = new Object();
    ...
    public void lockTraversal(Traversal<String> block) {
        synchronized (lock) {
            block.traverse(getAnIterator());
        }
    }
}
MyObj obj = (...)

obj.lockTraversal(new Traversal<String>() {
    public void traverse(Iterator<String> iter) {
        ...
    }
});

Java SE 8 からは、おそらく次の行に沿って何かを書くことができることを除いて、ほとんど同じです。

obj.lockTraversal({iter -> // Guess type of iter.
    ...
});

他の人が述べたように、java.util.concurrent.locksより少ない制約でロックを提供します。これらの制約を失うと、微妙なバグが発生する可能性があることに注意してください。たとえば、元の質問では、lockTraveralスローすると、一致するロックが成功せずにロックが解除される場合があります。

于 2013-04-09T08:08:18.867 に答える
1

オブジェクトの固有ロックでは実行できませんが、代わりに java.util.concurrent.locks.Lock を使用できます。

本当に必要で、危険を感じていて、移植性を心配していない場合は、misc.sun.Unsafe、具体的には monitorEnter と monitorExit を使用することもできます。しかし...おそらく良い考えではありません。

于 2013-04-09T07:51:38.020 に答える
1

ReentrantLockを使用できます。

それはまさにそれがすることです。

于 2013-04-09T07:53:07.420 に答える
1

ReentrantLock と Condition を使用して、ロックを解放できるタイミングを通知できます。

于 2013-04-09T07:53:10.323 に答える
0

java.util.concurrent.locksJava には、 Java 1.5 以降のパッケージに含まれている個別のロック フレームワークがあります。よりも広範なオプションを提供しますsynchronized

class X {
    private final ReentrantLock lock = new ReentrantLock();

    public void m() {
      lock.lock();  // block until condition holds
      try {
        // ... method body
      } finally {
        lock.unlock()
      }
    }
}
于 2013-04-09T07:57:45.637 に答える