7

競合状態を強制しようとした (または少なくともその発生確率を上げようとした) テストを作成しようとしましたが、CountDownLatch.

問題は、私java.lang.IllegalMonitorStateExceptionCountDownLatch.wait(). 私は確かに を誤用してCountDownLatchおり、このテストを巧妙な方法で作成していません。

この単純なコードは、私のアイデアと私の問題を再現します (私にはgistもあります):

import java.util.*;
import java.util.concurrent.*;

public class Example {

    private static BusinessLogic logic;

    public static void main(String[] args) {
        final Integer NUMBER_OF_PARALLEL_THREADS = 10;
        CountDownLatch latch = new CountDownLatch(NUMBER_OF_PARALLEL_THREADS);
        logic = new BusinessLogic();

        // trying to force the race condition
        List<Thread> threads = new ArrayList<Thread>(NUMBER_OF_PARALLEL_THREADS);
        for (int i=0; i<NUMBER_OF_PARALLEL_THREADS; i++) {
            Thread worker = new Thread(new WorkerRunnable(latch));
            threads.add(worker);
            worker.start();
        }

        for (int i = 1; i <= NUMBER_OF_PARALLEL_THREADS; i++) {
            try {
                threads.get(i).wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Just a dummy business logic class.
     * I want to "force" a race condition at the method doSomething().
     */
    private static class BusinessLogic {
        public void doSomething() {
            System.out.println("Doing something...");
        }
    }

    /**
     * Worker runnable to use in a Thead
     */
    private static class WorkerRunnable implements Runnable {
        private CountDownLatch latch;

        private WorkerRunnable(CountDownLatch latch) {
            this.latch = latch;
        }

        public void run() {
            try {
                // 1st I want to decrement the latch
                latch.countDown();
                // then I want to wait for every other thread to 
                latch.wait(); // the exception is thrown in this line.
                // hopefully increase the probability of a race condition...
                logic.doSomething();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

の javadoc には、現在のスレッドがオブジェクトのモニターの所有者でない場合にスローCountDownLatch.wait()されることが記載されています。IllegalMonitorStateExceptionしかし、私はこれが何を意味するのか理解できず、この例外を回避するためにコードを再作成する方法を理解することもできません.

編集:回答に記載されているヒントを使用して、上記の例の新しいバージョンを作成し、この gistに保存しました。今は例外はありません。

4

3 に答える 3

20

await()ではなく、試してみてくださいwait()

await()ラッチがゼロになるまで待機します。 wait()ラッチとは無関係であり、あなたが望むものではありませんWorkerRunnable。ただし、参考までに、例外を取得せずに呼び出すwait()には、オブジェクトのモニターを所有する必要があり、所有者になるには、synchronizedそのオブジェクトのブロックにいる必要があります。

于 2015-12-03T12:52:04.397 に答える
2

コントローラー スレッド (通常はメイン/UI スレッド) が待機し、ワーカー スレッドがカウントダウンを行う必要があります。

メインスレッドからスレッドを開始し、latch.await()そこに呼び出しを挿入する必要があります-それらを開始した直後。各ワーカー スレッドはlatch.countdown()、完了時に呼び出す必要があります。

allthreads が呼び出されるとcountdown()、CountDownLatch はメイン スレッドで終了latch.await()し、実行の制御をメイン スレッドに移します (その後のコードlatch.await()が実行を開始します)。

await()したがって、基本的には、ワーカー スレッドを開始した直後にメイン プログラムに移動する必要があります。

編集:Thread.wait()これは別のマルチスレッドフレームワークであるため、呼び出しも削除する必要があります-待機/通知であり、CountDownLatchを使用するよりもはるかに低レベルです(シミュレーションに必要でない限り。テストケースがよくわかりません)

于 2015-12-03T12:48:07.207 に答える
0

wait()any オブジェクトを呼び出そうとするときは、そのオブジェクトのモニターが必要です。

Object o = new Object();
o.wait();

を引き起こしますIllegalMonitorStateException

を呼び出せるようにするには、そのオブジェクトを同期する必要がありますwait()

Object o = new Object();
synchronized(o) {
    o.wait();
}
于 2015-12-03T12:48:31.117 に答える