Java Проблема параллелизма производителя / потребителя - исключение NoSuchElementFound при попытке чтения объектов - PullRequest
0 голосов
/ 28 января 2020

У нас есть реализация производителя-потребителя. Иногда мы получаем NoSuchElementException в методе readRecord (). В идеале этого не должно происходить, поскольку существует оператор if, а метод синхронизирован, что гарантирует выполнение только одного потока в любой момент времени. Но все же мы получаем NoSuchElementException. Может кто-нибудь, пожалуйста, подскажите мне это?

import java.util.LinkedList;
public class Listner{
    private LinkedList<Object> objList = new LinkedList<Object>();
    private Object listLock = new Object();

    public void writeRecord(Object obj){
        synchronized(listLock) {
            objList.add(obj);
        }
    }


    public synchronized Object readRecord(){
        Object obj = null;
        if( !objList.isEmpty() )
            obj = objList.removeFirst();
        return obj;
    }
}

1 Ответ

0 голосов
/ 28 января 2020

Ваш readRecord синхронизирован, поэтому одновременно может быть не более одного readRecord, но ничто не мешает одновременной работе readRecord и writeRecord, поскольку они блокируются на разных объектах. Если так случится, что writeRecord находится в процессе добавления записи, поэтому isEmpty возвращает false, но removeFirst не может найти элемент, потому что writeRecord еще не добавил его, вы получите это исключение.

Синхронизируйте на listLock в readRecord или избавьтесь от listLock и объявите оба метода синхронизированными, чтобы исправить это.

...