Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么此代码会导致illegalMonitorState异常?_Java_Java.util.concurrent - Fatal编程技术网

Java 为什么此代码会导致illegalMonitorState异常?

Java 为什么此代码会导致illegalMonitorState异常?,java,java.util.concurrent,Java,Java.util.concurrent,下面的代码试图将随机值插入循环队列并将其删除。但是,存在一些同步问题。我知道我可以使用更高级别的例程,我将对生产代码这样做,但我很好奇为什么这不起作用?我错过了什么 public class CircularQueue { int count; int rear; int front; Object lock = new Object(); int size; int[] array; CircularQueue(int size) { this.size= size; arra

下面的代码试图将随机值插入循环队列并将其删除。但是,存在一些同步问题。我知道我可以使用更高级别的例程,我将对生产代码这样做,但我很好奇为什么这不起作用?我错过了什么

public class CircularQueue {
int count;
int rear;
int front;
Object lock = new Object();
int size;
int[] array;
CircularQueue(int size)
{
    this.size= size;
    array = new int[size];
}

void enqueue(int number) throws InterruptedException
{
    if(isFull())
        lock.wait();

    synchronized(lock)
    {

        array[rear] = number;
        System.out.println("Rear is:"+ rear+ "value is:"+number+"Size is:"+size);

        rear = (rear+1)%size;
        count++;
    }
    lock.notify();

}

void dequeue() throws InterruptedException
{
    if(isEmpty())
        lock.wait();

    synchronized(lock)
    {
        int retVal = 0;
        retVal = array[front];
        System.out.println("Front is:"+ front+ "value is:"+retVal);

        front = (front+1)%size;
        count--;
    }

    lock.notify();

}

boolean isFull()
{
    if(count == size)
    {
        return true;
    }
    else
        return false;

}

boolean isEmpty()
{
    return count == 0;
}
}
//测试班

import java.util.Random;
public class App {

    public static void main(String[] args) throws InterruptedException
    {
       final Random random = new Random();
       final CircularQueue circularQueue = new CircularQueue(10);
       Thread t1 = new Thread(new Runnable(){

        @Override
        public void run() {
            try {
                circularQueue.enqueue(random.nextInt(100));
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

       });
       Thread t2 = new Thread(new Runnable(){

            @Override
            public void run() {
                try {
                    circularQueue.dequeue();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

           });

       t1.start();
       t2.start();
       t1.join();
       t2.join();

    }

}

因为
java.lang.Object#wait
java.lang.Object#notify
java.lang.Object#notifyAll
必须从同步块调用

作为解决方案(需要检查),您应该将您的条件放入同步块中:

void enqueue(int number) throws InterruptedException
{

    synchronized(lock)
    {
        if(isFull())
           lock.wait();

        array[rear] = number;
        System.out.println("Rear is:"+ rear+ "value is:"+number+"Size is:"+size);

        rear = (rear+1)%size;
        count++;
        lock.notify();
    }
}

void dequeue() throws InterruptedException
{
    synchronized(lock)
    {
        if(isEmpty())
           lock.wait();

        int retVal = 0;
        retVal = array[front];
        System.out.println("Front is:"+ front+ "value is:"+retVal);

        front = (front+1)%size;
        count--;
        lock.notify();
    }

}

此代码中的另一个问题是,即使isEmpty/isFull返回true,在调用相邻的wait之前,队列的状态可能会改变。
例如:
-队列为空
-线程1调用isEmpty()
-上下文切换
-线程2调用队列(现在队列不是空的)
-上下文切换
-线程1不调用lock.wait()事件,尽管队列不是空的

当对wait()/notify()的调用放在同步块中时,这个问题当然会得到解决