Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring竞争条件单例服务有状态或无状态_Java_Multithreading_Spring_Spring Mvc_Race Condition - Fatal编程技术网

Java Spring竞争条件单例服务有状态或无状态

Java Spring竞争条件单例服务有状态或无状态,java,multithreading,spring,spring-mvc,race-condition,Java,Multithreading,Spring,Spring Mvc,Race Condition,我有点担心使用Spring的比赛条件。 我知道各种作用域之间的区别(单例、原型、会话等等) 我也知道: 默认情况下,服务具有单例作用域 只要我的bean是无状态的,我就不会有竞争条件方面的问题 尽管我不是百分之百确定这个无状态的事情。我的研究来源在谈到状态性时总是只关注共享实例变量,但竞争条件不仅在访问实例变量时才会出现。 我创建了以下示例来说明我的问题: @Service public class AppleService { @Autowired private AppleRe

我有点担心使用Spring的比赛条件。 我知道各种作用域之间的区别(单例、原型、会话等等)

我也知道:

  • 默认情况下,服务具有单例作用域
  • 只要我的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));
  } 
}
@服务
公共类应用程序服务{
@自动连线
私人申请储蓄申请储蓄;
@凌驾
公共void doSomethingWithAppleCategory(字符串appleCategory){
布尔existsAppleInCategory=existsAppleInCategory(appleCategory);
if(现有的SAPPLEINCATEGORY){
//做点什么
}
否则{
抛出新的RuntimeException(“类别:“+AppleCegory”中没有apple);
}
}
私有布尔existsAppleInCategory(字符串AppleCegory){
Iterable allApples=appleRepository.findAll();
返回allApples.stream().anyMatch(a->a.getAppleCategory().equals(appleCategory));
} 
}
您可以假设该服务是在rest控制器或类似的东西中使用的。根据我的理解,当方法存在时,可能存在竞争条件问题。调用Pleincategory。例如,thread1有其插槽,并将“false”写入变量existsAppleInCategory。然后线程2的插槽将用“true”覆盖existsAppleInCategory。之后,线程1有另一个时隙。=>线程1现在“做了一些事情”,而不是抛出RuntimeException

我的假设正确吗?在这种情况下,我在比赛条件方面有问题吗? 如果不是,为什么?你能推荐一些关于这个主题的详细资料吗(在线资料、书籍等)


提前谢谢你 Apple ErpRePosie<代码>有状态,因为正如你在你的例子中描述的,它可以改变。p> <> P>因此,你必须在这个类中考虑线程安全性(也许是序列化?)。显然,您的
AppleService
是线程安全的,因为它是无状态单例。您的竞争条件问题将来自存储库,而不是单例


一个好的基本读取

是的,这里可以从数据库级别查看竞争条件

如果查询数据,然后在 同一事务,常规SELECT语句没有提供足够的 保护。其他事务可以更新或删除与您相同的行 我只是问

因此,使用数据库锁定方法

锁定读取(选择…进行更新,然后选择…锁定共享) 模式)

如果要在java中保护竞争条件,请在代码级别使用
同步

更多信息:

Mysql:


PlSQL:

正如M.Deinum在其评论中所说,您的代码没有任何竞争条件问题,因为
existsAppleInCategory
是函数的局部变量,而不是实例变量。每个线程都有自己的副本,一切正常

这将是完全不同的

@Service
public class AppleService {

  @Autowired
  private AppleRepository appleRepository;

  private boolean _existsAppleInCategory;

  @Override
  public void productCallDetection(String appleCategory) {
    _existsAppleInCategory = existsAppleInCategory(appleCategory);
    if(existsAppleInCategory) {
        // do something
    }
    ...
  }
  ...
}

因为现在您正在更改一个将由所有线程共享的实例变量。

假设
AppleRepository
是一个无状态的单例,并在其中省略数据库(如您的问题涉及java)

简言之,thread1无法看到thread2中的变量,因此您没有任何并发性问题

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


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

否。您的理解是错误的。。。没有共享状态(假设
applereposition
也是线程安全的单例)。每个线程都有自己的堆栈,在该堆栈上,除其他外,还有方法内部使用的变量,因此thread1无法从thread2中看到
存在的Pleincategory
,反之亦然。如果
existsAppleInCategory
是实例级变量,则情况会有所不同!。你当然是对的。现在我觉得自己是个初学者:-)