【问题标题】:ConcurrentModificationException in Spring Boot CRUD repositorySpring Boot CRUD 存储库中的 ConcurrentModificationException
【发布时间】:2021-05-31 09:46:59
【问题描述】:

这是一个理论问题。我想了解在 Spring Boot 中使用 CRUD 存储库时出现ConcurrentModificationException 的可能原因。

更准确地说,我有一个特定的问题,我希望得到“是”或“否”的答案。知道异常有时会被myRepository.saveAll(myArrayList); 行抛出,并且myRepository 在不同的线程中被使用,这个saveAllfindById,是否有可能在@987654326 的不同线程中并行执行@ 和 findById 会产生这样的异常吗?我希望答案是“不”,但我不确定。如果答案是“是”,我将不清楚如何解决问题。

如果答案是“否”,是否会导致有时会引发此异常的唯一情况是在不同线程中同时使用myArrayList(我的代码这样做),即修改(添加元素) myArrayList 由一个线程执行,而 saveAll 正在另一个线程中执行?如果是这样,将saveAllmyArrayList.add(...) 代码包含在synchronized (myArrayList) {} 中是否足够?

为了完整起见,myRepository 是一个简单扩展 CrudRepository 的接口,并带有 @Repository@Transactional 注释。

感谢您的澄清。

【问题讨论】:

  • 即使 Spring CRUDRepository 可能是一个问题(据我所知它们是 threadsafe),在不同步的情况下使用来自不同线程的 ArrayList 实例是不安全的

标签: spring-boot


【解决方案1】:

saveAll和findById不同线程并行执行会不会产生这样的异常

否 - 这些方法是 threadsafe

这是否意味着有时可以抛出的唯一情况 这个例外是 myArrayList 在不同的并发使用 线程(我的代码这样做),即修改(添加元素) 在执行 saveAll 时由一个线程调用 myArrayList 另一个线程?

根据您的问题陈述 - 上述处理是您遇到异常的最可能原因。话虽如此 - ConcurrentModificationException 集合通常可能是由单线程引起的。如果您在迭代集合时修改了集合 - 那么抛出此异常是实现集合所采用的快速失败机制。例如,下面的代码如果在单线程中运行仍然会抛出这个异常

List<Integer> integers = new ArrayList(1, 2, 3);
    for (Integer integer : integers) {
        integers.remove(1);
    }

ConcurrentModificationException的文档中可以更详细的了解。

请注意,此异常并不总是表明对象具有 被不同的线程同时修改。如果单线程 发出一系列违反合同约定的方法调用 一个对象,该对象可能会抛出这个异常。例如,如果一个 线程在迭代集合时直接修改集合 带有快速失败迭代器的集合,迭代器将抛出这个 例外。

【讨论】:

    猜你喜欢
    • 2017-03-28
    • 2019-03-10
    • 2014-02-03
    • 2020-05-05
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多