0
import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

class Foo {
    private ReentrantLock _lock;
    private Condition _cond;
    private Thread _thr;
    private LinkedList<String> _msgQueue;

    public Foo() {
        _lock = new ReentrantLock();
        _cond = _lock.newCondition();
        _msgQueue = new LinkedList<String>();
        startThread();
    }

    public void putMsg(String msg) throws Exception {
        _lock.lock();
        _msgQueue.addLast(msg);
        _cond.signal();
        System.out.println(Thread.currentThread().getId() + ": Signal write thread.");
        _lock.unlock();
        System.out.println(Thread.currentThread().getId() + ": Unlocked.");
    }

    private void startThread() {
        _thr = new Thread() {
            public void run() {
                _lock.lock();
                while(true) {
                    try {
                        while (!_msgQueue.isEmpty()) {
                            String msg = _msgQueue.getFirst();
                            System.out.println(msg);
                            _msgQueue.removeFirst();
                        }

                        System.out.println(Thread.currentThread().getId() + ": getHoldCount:" + _lock.getHoldCount());
                        System.out.println((Thread.currentThread().getId() + ": isLocked:" + _lock.isLocked()));
                        System.out.println(Thread.currentThread().getId() + ": isHeldByCurrentThread:" + _lock.isHeldByCurrentThread());
                        System.out.println(Thread.currentThread().getId() + ": Awaiting...");

                        _cond.await();

                        System.out.println(Thread.currentThread().getId() + ": Write thread awaken");

                    } catch (Exception e) {
                        e.printStackTrace();
                        break;
                    } finally {
                        try {
                            _lock.unlock();
                        } catch (Exception e) {
                        }
                    }
                }
                System.out.println("Write thread exit.");
            }
        };

        _thr.start();
    }
}

public class LockTest {
    public static void main(String[] args) throws Exception {
        Foo foo = new Foo();
        foo.putMsg("Msg 1");
        foo.putMsg("Msg 2");
        Thread.sleep(1000);
        foo.putMsg("Msg 3");
    }
}
実行後のコード出力:
1: シグナル書き込みスレッド。
1: ロック解除。
1: シグナル書き込みスレッド。
1: ロック解除。
メッセージ 1
メッセージ 2
8: getHoldCount:1
8: isLocked:true
8: isHeldByCurrentThread:真
8: 待っています...
1: シグナル書き込みスレッド。
1: ロック解除。
8:スレッド覚醒を書く
メッセージ 3
8: getHoldCount:0
8: isLocked:false
8: isHeldByCurrentThread:false
8: 待っています...
スレッド出口を書き込みます。
java.lang.IllegalMonitorStateException at

java.util.concurrent.locks.ReentrantLock$Sync.tryRelease (不明なソース) で

java.util.concurrent.locks.AbstractQueuedSynchronizer.release (不明なソース) で

java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease (不明なソース) で

java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(不明なソース)

Foo$1.run(LockTest.java:44) で

質問は次のとおりです。http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Condition.html#await()によると、スレッドが返されたときに、このロックを保持します。しかし、出力から、await() が戻った後、ロックを再取得していないことがわかります。これはバグですか、それとも私が犯したいくつかの間違いですか?

4

1 に答える 1

1

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Condition.html#await()によると、スレッドが戻ると、このロックを保持することが保証されます。

確かに、メソッドを呼び出す前にスレッドがロックを保持する必要があることも示しています。

現在のスレッドは、このメソッドが呼び出されたときに、この Condition に関連付けられたロックを保持していると見なされます。これが当てはまるかどうか、そうでない場合はどのように応答するかを決定するのは実装次第です。通常、例外がスローされ (IllegalMonitorStateException など)、実装はその事実を文書化する必要があります。

これは、「通常の」モニター (Object#wait) と同じように機能します。待機を開始するときは、ロックを保持する必要があります (Object#wait の場合は同期ブロック、ここでは Lock#lock を使用)。その後、ロックが解除され、待機します。待機が終了すると、再びロックを保持します。

于 2013-07-24T04:22:50.513 に答える