3

synchronized()この投稿の最後に書いたプログラムのブロックを理解しようとしています。

共有オブジェクトを待機/通知のモニターとして使用する2 つのスレッド (oおよび) があります。klock

ok次の同期ブロック内で、開始を待機します。

synchronized (lock) {
    lock.wait(); // wait for K to be ready
}

k次に、通知oして、このブロック内で印刷されるのを待ちます。

synchronized (lock) {
    lock.notify(); // tell O to print
    lock.wait(); // wait for O to print
}

私の質問は、どのようkにして同期ブロックに入ることができますlockか? o所有すべきではないlock(と呼ばれているためwait())? Javaチュートリアルには次のように書かれています:

スレッドが固有ロックを所有している限り、他のスレッドが同じロックを取得することはできません。他のスレッドは、ロックを取得しようとするとブロックされます。

完全なプログラムは次のとおりです。

public class OK implements Runnable {

    private static final Object lock = new Object(); // monitor for wait/notify

    private boolean isO;

    public OK(boolean b) {
        isO = b;
    }

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

        Thread o = new Thread(new OK(true));
        Thread k = new Thread(new OK(false));
        o.start();
        k.start();
        k.join(); // when k is done, we're done
        System.out.println("Done.");

    }

    public void run() {

        // run method is called for both o and k, so we separate the logic
        try {
            if (isO) {
                doO();
            } else {
                doK();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    // O thread logic
    private void doO() throws InterruptedException {

        // K needs to be ready before I start
        synchronized (lock) {
            lock.wait(); // wait for K to be ready
        }

        System.out.print("O");
        synchronized (lock) {
            lock.notify(); // tell K I printed
        }
    }

    // K thread logic
    private void doK() throws InterruptedException {

        // O is waiting for me to start

        synchronized (lock) {
            lock.notify(); // tell O to print
            lock.wait(); // wait for O to print
        }
        System.out.println("K");
    }

}
4

3 に答える 3

6

lock.wait はモニターを解放します。Object.wait() javadocを参照してください。

現在のスレッドは、このオブジェクトのモニターを所有している必要があります。スレッドは、このモニターの所有権を解放し、別のスレッドが、このオブジェクトのモニターで待機しているスレッドに、notify メソッドまたは notifyAll メソッドの呼び出しによってウェイクアップを通知するまで待機します。スレッドは、モニターの所有権を再度取得できるまで待機し、実行を再開します。

直感的に、「同期 (ロック)」とは、ラップするブロック全体でそのロックを保持することを意味することがわかります。しかし、それはそれがどのように機能するかではありません。

于 2013-03-24T05:40:42.883 に答える
2

@Wouter Coekaertsの回答に加えてwait()、「誤ったウェイクアップ」が発生する可能性があるため、常にループ内に電話をかけることをお勧めします。参照:THI03-J。たとえば、ループ内では常にwait()メソッドとawait()メソッドを呼び出します。

于 2013-03-24T05:45:00.477 に答える
1

マルチスレッドに関しては、動作は保証されません。これは、実行中のスレッドのプールからスレッドを呼び出すスケジューラーに完全に依存します。スレッドKの前にスレッドOを開始したからといって、スレッドOがスレッドKの前に呼び出されることを保証することはできません。また、スケジューラーがスレッドKを取得して最初に実行を開始し、スレッドOの前にロックを取得することもあります。

于 2013-03-24T05:43:47.097 に答える