7

我试图创建一个测试,我试图强制竞争条件(或至少增加其发生的可能性)并且我使用了CountDownLatch.

问题是我java.lang.IllegalMonitorStateException在我的CountDownLatch.wait(). 我当然在滥用,CountDownLatch而且我肯定不会以聪明的方式创建这个测试。

这个简单的代码重现了我的想法和我的问题(我也有一个要点):

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();
            }
        }
    }
}

如果当前线程不是对象监视器的所有者,则抛出的CountDownLatch.wait()状态的 javadoc 。IllegalMonitorStateException但恐怕我不明白这意味着什么,我也无法弄清楚如何重新创建我的代码来避免这个异常。

编辑:根据答案中提供的提示,我创建了上面示例的新版本,并将其存储在这个 gist中。我现在没有任何例外。

4

3 回答 3

20

试试await(),不行wait()

await()将等到锁存器达到零。 wait()与闩锁无关,也不是您想要的WorkerRunnable. 但是仅供参考,为了在wait()没有异常的情况下调用,您必须拥有一个对象的监视器,并且要成为所有者,您必须位于synchronized该对象上的一个块中。

于 2015-12-03T12:52:04.397 回答
2

您的控制器线程(通常是 main/ui 线程)应该进行等待,而工作线程则进行倒计时。

您应该从主线程启动线程并在其中插入latch.await()调用 - 就在您启动它们之后。每个工作线程都应该latch.countdown()在完成时调用。

当所有线程调用countdown()完 CountDownLatch 将退出latch.await()主线程并将执行控制权转移给它(之后的代码latch.await()将开始执行)。

因此,基本上您需要await()在启动工作线程后立即将其移至主程序。

编辑:您还应该删除Thread.wait()调用,因为这是另一个多线程框架 - 等待/通知,它比使用 CountDownLatch 低得多(除非您需要它进行模拟。我不太了解您的测试用例)

于 2015-12-03T12:48:07.207 回答
0

当尝试调用wait()任何对象时,您必须拥有该对象的监视器。

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

会导致IllegalMonitorStateException.

您必须在该对象上进行同步才能调用wait()

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