4

ReentrantLock.lock() の動作を理解するのに苦労しています

私は次のクラスを持っています

import java.util.concurrent.locks.*;

class BlockingClass {

    private Lock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();

    public void a() {
        lock.lock();
        System.out.println("called in method a(): lock()");

        try {
            System.out.println("called in method a(): await()");
            condition.await();
        } 
        catch (InterruptedException e) {} 
        finally {
            lock.unlock();
            System.out.println("called in method a(): unlock() ");
        }
    }

    public void b() {
        lock.lock();
        System.out.println("called in method b(): lock()");

        System.out.println("called in method b(): signalAll()");
        condition.signalAll();

        lock.unlock();
        System.out.println("called in method b(): unlock() ");
    }
}

次のテストで実行します。

class BlockingClassTest {
    public static void main(String[] args) throws InterruptedException {

        final BlockingClass blockingClass = new BlockingClass();

        new Thread() {
            public void run() {
                System.out.println("Thread1 calling a()");
                blockingClass.a();
            }
        }.start();

        Thread.sleep(1000); 

        new Thread() {
            public void run() {
                System.out.println("Thread2 calling b()");
                blockingClass.b();
            }
        }.start();
    }
}

私はデッドロックを予想していたでしょう。a() メソッドが lock.lock() を呼び出すと、b() メソッドを呼び出す人は、a() を呼び出すスレッドが lock.unlock() を呼び出すまで、b の lock.lock() で待機する必要があると思います。しかし、a() は b() が condition.signalAll() を呼び出すのを待っているため、両方のメソッドは永久にブロックされたままになっているはずです。

代わりに、これはコンソールに表示される出力です。

Thread1 calling a()
called in method a(): lock()
called in method a(): await()
Thread2 calling b()
called in method b(): lock()
called in method b(): signalAll()
called in method a(): unlock() 
called in method b(): unlock() 

lock() と unlock() の適切な使用と機能について、私は何を誤解していますか?

4

3 に答える 3

6

あなたは誤解していませんReentrantLock、あなたは誤解していますCondition。AConditionはロックにバインドされており、Condition.await()効果的にロックを解除し、チェックして待機し、ロックを再ロックします。を参照してくださいCondition.await()

、と の呼び出しa()の間、および と の戻りの間で、ロックは期待どおりに動作しています。への呼び出しの中で、がそれを管理しています。lock()await()await()unlock()await()Condition

これは、「条件変数」の一般的な概念の一部です。これが、スレッド ライブラリが何らかのロックを条件に関連付けている理由です (たとえば、POSIX C ではpthread_cond_wait、条件変数ミューテックスの両方が必要です)。

ウィキペディアの条件変数に関する記事を参照してください。この動作とその理由が詳しく説明されています。

于 2014-03-02T20:51:52.307 に答える
2

を呼び出すとcondition.await();ロックが解放され、スレッドはあるwait状態のままになるため、スレッド b はロックを取得できます。

条件を通知したため、ロックが解除されると、a()メソッドは引き続き実行されます。b()

于 2014-03-02T20:51:59.230 に答える