2

Java でスレッドを使用するのは初めてです。ライターがスレッドに入ると、リーダーはライターが完了するのを待つという単純なリーダーライターの問題があります。

しかし、自分のプログラムを実行すると、自分のスレッドに通知が届かないことに気づきましたか? どうしてこれなの?

私のコードは以下の通りです:

public class ReaderWriter  {

Object o = new Object();
volatile boolean writing;
Thread readerThread = new Thread( "reader") {

    public void run() {

        while(true) {
            System.out.println("reader starts");
            if(writing) {
            synchronized (o) {
                try {
                    o.wait();
                    System.out.println("Awaked from wait");
                } catch (InterruptedException e) {                      
                    e.printStackTrace();
                }

            }
        }

            System.out.println( "reader thread working "+o.hashCode());

        }

    }
};
Thread writerThread = new Thread("writer" ) {
    public void run() {
        System.out.println( " writer thread");
        try {
            synchronized (o) {
                writing = true;
                System.out.println("writer is working ..  ");
                Thread.sleep(10000);                    
                writing = false;
                o.notify();
                System.out.println("reader is notified");
            }


        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
};

public static void main(String[] args) {
    ReaderWriter rw=new ReaderWriter();
    rw.readerThread.start();

    rw.writerThread.start();

}

}

4

5 に答える 5

4

ここで問題はsynchronized (o)関数にあります。

同期関数はスレッドを同期させ、オブジェクトに対して一度に 1 つのスレッドのみを実行しますo。したがって、一方の値writingは true です。2 番目の踏み板 readerThreadsynchronized (o)readerThread

終了ステートメントがないため、無限ループが発生しています。スレッドがいつ終了するかを知るには、ここ
を参照して ください

このコードを見て、同期関数について詳しく知る

synchronized(object) {
   // statements to be synchronized
}

ここで、 object は同期されるオブジェクトへの参照です。同期ブロックにより、オブジェクトのメンバーであるメソッドへの呼び出しが、現在のスレッドがオブジェクトのモニターに正常に入った後にのみ発生することが保証されます。

.

これを読んで、通知方法について確認してください

JavaSW の Object クラスには、スレッドがリソースのロック状態について通信できるようにする 3 つの最終メソッドがあります。これらのメソッドは、wait()、notify()、および notifyAll()です。スレッドは、そのリソースのインスタンスと同期されたブロックを介して、特定のリソースのロックを取得します。あるスレッドが、リソースに作用する前に、別のスレッドがそのリソースに対して特定のアクションを実行することを要求するとします。そのスレッドは、リソースで同期し、リソースで wait() メソッドを呼び出すことができます。これは、スレッドが処理を続行できることが通知されるまで待機することを示しています。

wait() メソッドは、オプションのタイムアウト値をパラメーターとして取ることができます。この値が使用される場合、スレッドは通知されるまで待機するか、タイムアウト値が経過しても実行を継続することを意味します。

別のスレッドがリソースで動作する前にスレッドがリソースでタスクを実行する必要がある場合 (および他のスレッドがリソースのwait()メソッドを介して待機している場合)、スレッドはリソースで同期する必要があります。リソースに対してアクションを実行できます。

これらのアクションが完了したら、待機中のスレッドに通知するためnotify()に、リソースのメソッドが呼び出されます。これにより、待機中のスレッドに、処理を続行できることが通知されます。複数のスレッドがリソースを待機している場合、どのスレッドにリソースへのアクセスが許可されるかは保証されません。待機中のすべてのスレッドを起動する必要がある場合はnotifyAll()、リソースでメソッドを呼び出すことができます。

于 2013-08-26T14:29:31.613 に答える
1

ライター スレッドは、writingが に設定されている間、常にモニター オブジェクトのロックを保持していますtrue。これが、が に設定されている間、リーダー スレッドの同期ブロックに入ることがない理由です。writingtrue

synchronized (o) { // Thread aquires lock on monitor o. writing is false.
    writing = true; // writing is true, lock still held.
    System.out.println("Writer is working...");
    Thread.sleep(1000); // Thread sleeps while holding lock.
    writing = false; // writing is changed back to false, lock still held.
    o.notify();
    System.out.println("Reader is notified");
} // Here lock is released, writing is false.

つまり、ロックを取得する前にwriting設定され、ロックを解除するときに設定されます。ロックが保持されている間、リーダー スレッド内のこの同期ブロックは入力されません。falsefalse

while (true) {
    if (writing) {
        synchronized (o) { // Lock always held by writer when writing=true.
            try {
                o.wait();
                System.out.println("Awaked from wait");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
于 2013-08-26T14:59:08.887 に答える