notifyAll如何在这种情况下工作?

时间:2014-08-24 14:08:20

标签: java multithreading

这是我写的多线程队列的小片段,

synchronized void add(int i) {
    if (count == size) {
        System.out.println("******full***");
        isQueueFull = true;
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    System.out.println("adding number: " + i);
    val[end++] = i;
    count++;
    if (isQueueEmpty) {
        isQueueEmpty = false;
        this.notifyAll();
    }
}



synchronized int remove() {
    if (count == 0) {
        isQueueEmpty = true;
        System.out.println("******empty***");
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    int t = val[0];
    for (int i = 0; i < end - 1; i++) {
        val[i] = val[i + 1];
    }
    val[end - 1] = -1;
    end--;
    count--;

    if (isQueueFull) {
        isQueueFull = false;
        this.notifyAll();
    }
    System.out.println("removing number: " + t);
    return t;

}

假设我有四个线程添加到队列中,一个线程从队列中删除。有一次,假设数组已满,我在添加到队列的所有四个线程上调用wait。

现在当一个元素被删除时,我需要在所有休眠线程上调用notifyAll。(它给了我一个arrayOutofBound异常)我的问题是这样,在notifyAll的情况下线程流是什么。

由于add是synchronized方法,因此只能执行一个线程。但由于等待,我们现在有四个线程在其中睡觉。那么在notifyAll上,所有四个线程是否仍然在add方法中(尽管它是一个同步方法)并执行?或者它将按顺序逐个完成,所有线程都被锁定,直到一个线程完成。

我很难在eclipse中调试它。我通过在等待之后放置一个return语句来解决arrayOutOfBoundException,但我还是想了解notifyAll的情况下的流程?

1 个答案:

答案 0 :(得分:2)

等待与睡觉有很大不同。 javadoc of wait()解释了它:

  

线程释放此监视器的所有权并等待,直到另一个线程通过调用notify方法或notifyAll方法通知等待此对象监视器的线程唤醒。 线程然后等待,直到它可以重新获得监视器的所有权并继续执行。

(强调我的)

顺便说一下,它还包含一条你不尊重的强有力的规则:

  

与一个参数版本一样,中断和虚假唤醒是可能的,此方法应始终在循环中使用

 synchronized (obj) {
     while (<condition does not hold>)
         obj.wait();
     ... // Perform action appropriate to condition
 }

因此,当调用notifyAll()时,4个线程竞争返回监视器。一旦前一个释放它,每个人都会收回它,然后继续执行。