Java 生产者/消费者并发问题 - 尝试读取对象时出现 NoSuchElementFound 异常

标签 java concurrency linked-list synchronized producer-consumer

我们有生产者消费者的实现。 有时我们会在 readRecord() 方法中遇到 NoSuchElementException。 理想情况下,这种情况不应该发生,因为有一个 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;
    }
}

最佳答案

您的 readRecord 是同步的,因此一次最多可以有一个 readRecord,但是没有什么可以阻止 readRecordwriteRecord 并发运行,因为它们锁定不同的对象。如果碰巧 writeRecord 正在添加记录,则 isEmpty 返回 false,但 removeFirst 无法找到该元素,因为 writeRecord 尚未完成添加,您会收到该异常。

readRecord 中对 listLock 进行同步,或者删除 listLock 并将这两个方法声明为同步来修复它。

关于Java 生产者/消费者并发问题 - 尝试读取对象时出现 NoSuchElementFound 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59942497/

相关文章:

Android Camera 不会拍照,具体取决于代码中的内容

java - 真值表 - 帮助

java - 如何实现 java.text.Format

java - 如何在 Ubuntu 上更新已经安装的 IntelliJ IDEA?

c - 我正在尝试编写一个函数,从给定的链表中删除所有奇数元素,并返回一个地址

c++ - std::forward_list 是否支持手动重新指向?

c++ - 链表 C++ 中的复制构造函数

java - 如何在 Spring 中从 JNDI 引用多个 bean?

go - 结果到达时如何管理缓存服务器上的重复请求

java - 避免在多线程代码中使用关闭标志