java - Spring race conditions 单例服务有状态还是无状态

标签 java multithreading spring spring-mvc race-condition

我有点担心使用 Spring 的竞争条件。 我知道各种作用域(单例、原型(prototype)、 session 等)之间的区别

我也知道:

  • 默认情况下,服务具有单例范围
  • 只要我的 bean 是无状态的,我就不会遇到竞争条件问题

尽管我对这个无状态的东西不是百分百确定。在谈论有状态时,我的研究来源总是只关注共享实例变量,但竞争条件不仅会在访问实例变量时出现。 我创建了以下示例来说明我的问题:

@Service
public class AppleService {

  @Autowired
  private AppleRepository appleRepository;

  @Override
  public void doSomethingWithAppleCategory(String appleCategory) {
    boolean existsAppleInCategory = existsAppleInCategory(appleCategory);
    if(existsAppleInCategory) {
        // do something
    }
    else {
        throw new RuntimeException("There is no apple in the category: " + appleCategory);
    }
  }

  private boolean existsAppleInCategory(String appleCategory) {
    Iterable<Apple> allApples = appleRepository.findAll();
    return allApples.stream().anyMatch(a -> a.getAppleCategory().equals(appleCategory));
  } 
}

您可以假设该服务用于休息 Controller 或类似的东西。根据我的理解,当调用 existsAppleInCategory 方法时,竞争条件可能会出现问题。例如,thread1 有它的槽并将“false”写入变量 existsAppleInCategory。然后线程 2 将其插槽覆盖为“true”的 existsAppleInCategory。之后线程 1 有另一个时隙。 => 线程 1 现在“做某事”而不是抛出 RuntimeException。

我的假设是否正确?在这种情况下我是否遇到竞争条件问题? 如果不是为什么?您能否推荐任何详细描述该主题的资源(在线资源、书籍……)?

提前致谢!

最佳答案

假设 AppleRepository 是一个无状态的单例并且在其中省略了数据库(因为你的问题是关于 java 的)。

简而言之,thread1 看不到 thread2 的变量,因此您没有任何并发​​问题。

每个正在执行的线程都有自己的堆栈,在该堆栈上,除其他外,还有方法内部使用的变量,因此线程 1 无法从线程 2 看到 existsAppleInCategory,反之亦然。该变量是方法的本地变量(实际上是执行 block ),每个线程在堆栈上都有自己的副本。

如果 existsAppleInCategory 是一个实例级变量,那么这将有所不同,因为您将拥有共享状态。在这种情况下,线程可能会看到彼此的数据(取决于写入/读取状态的时间以及 volatile 关键字的使用)。

关于java - Spring race conditions 单例服务有状态还是无状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32779630/

相关文章:

c++ - Boost线程泄漏C++

java - POST 并将嵌套对象持久保存到 Spring MVC

java - 如何将一个对象的特定字段映射到另一个对象?

java - Ubuntu 上无法上传文件

java - ZK Controller 中java空指针异常

java - 如何限制一个任务使用线程池中的所有线程?

java - Hibernate延迟加载不起作用,强制需要急切加载

java - LWJGL,openGL 多重纹理

java - Apache 使用 modjk 作为 WordPress 和 Tomcat 的代理

java - 在 Java 中使用多个线程