Синхронизация двух классов - PullRequest
1 голос
/ 09 ноября 2019

У меня есть 4 класса: Main, Producer, Consumer и Buffer. Буферный класс содержит реализацию для кольцевого массива (предположим, что он работает). Класс производителя добавляет в буферный массив, а потребительский класс удаляет из буферного массива. Класс Main создает поток для производителя и для потребителя.

Внутри класса производителя, если буфер не заполнен, он добавляется к нему. Если он заполнен, он ожидает, пока потребитель не удалит что-либо из массива.

Внутри класса Consumer, если буфер не пустой, он удаляет из него элемент. Если он пуст, он ждет, пока производитель добавит что-то в буфер.

Проблема, с которой я столкнулся, заключается в том, что производитель будет добавлять элементы в массив, но каждый раз, когда он уведомляет потребителя, что он добавил вбуфер, потребитель остается в состоянии ожидания. Это никогда не продолжается с остальной частью кода.

// Main.java
Buffer buffer = new Buffer(5); // creates a circular array of length 5.

// 10 is total number of items to be added
Producer p = new Producer(buffer, 10); // uses random number generator for values 
Consumer c = new Consumer(buffer, 10);

p.start();
c.start();

p.join();
c.join();
public class Producer extends Thread {

    ...

    public void run() { 
        ...
        while(true) {
            synchronized(this) {
                try {
                    while(buffer.isFull()) wait(); 
                    ...
                    buffer.insert(val);
                    notify();
                    ... // other stuff that eventually breaks the loop
                } catch(InterruptedException e) {}
            }
        }
    }
}
public class Consumer extends Thread {

    ...

    public void run() {
        while(true) {
            synchronized(this) {
                try {
                    while(buffer.isEmpty()) wait(); // its stuck here
                    ...
                    buffer.remove();
                    notify();
                    ... // other stuff that eventually breaks the loop
                } catch (InterruptedException e) {}
            }
        }
    }
}

// Inside Buffer.java

public void insert(int n) {
    ...
    buffer[front] = n;
    front++;
    size++;
}

public int remove() {
    ...
    temp = buffer[rear] = -1;
    rear--;
    size--;
    return temp;
} 

В производителе есть оператор print, который печатает 5 значений, которые были добавлены в буфер (максимальный размербуфер) но потом ничего не происходит после этого. Producer добавляет значения в массив и затем переходит в состояние ожидания, но Consumer ничего не делает, поскольку он все еще остается в состоянии ожидания.

Я не могу понять, почему Consumer не продолжает работу, несмотря на то, что Producer выполняет уведомление каждый раз, когда добавляет что-то в буфер.

1 Ответ

2 голосов
/ 09 ноября 2019

В вашем коде synchronized(this) бессмысленно, так как Consumer и Producer являются независимыми объектами. Каждый из этих объектов имеет свой собственный this монитор, к которому другой не имеет доступа. Вы застряли в Consumer на while(buffer.isEmpty()) wait();, потому что ничто в Producer не вызывает cosumer.notify().

Скорее всего, это должно быть synchronized(buffer) (за которым следуют buffer.wait() и buffer.notify()), поскольку этоbuffer объект, представляющий общее состояние в вашем коде.

Вы переопределяете java.util.concurrent.ArrayBlockingQueue на Buffer. Почему бы не использовать класс, который уже доступен в JDK?

...