【问题标题】:How to fix Fortify Race Condition: Singleton Member Field issue如何修复 Fortify Race Condition:Singleton Member Field 问题
【发布时间】:2016-12-10 00:30:15
【问题描述】:

我遇到了一个问题。 我们在我的项目中使用 Spring MVC 框架,但 Spring MVC 默认控制器是单例模型。 我通过会话更改控制器使用 @Scope("session") 以避免竞争条件问题(每个人都有自己的控制器)。

@Controller
@Scope("session")
public class AP0Controller extends BaseController {

    @Autowired
    GnRecService gnRecService;

    Integer seq = null;//Global variable

    @RequestMapping(value = "/agn/AP1W01A_004", method=RequestMethod.GET)
    public ModelAndView welcomeGrid(@RequestParam("payType")String payType){
        seq = gnRecService.findTheLastPK(payType);
        ModelAndView view = new ModelAndView(".agn.AP1W01A_004");
        return view;
    }

    public ModelAndView showPk() {
        seq +=2; 
        ModelAndView view = new ModelAndView(".agn.AP1W01A_004");
        view.addObject("seq",seq)
        return view;
    }

}

HP Fortify 扫描后,报告显示这将导致竞争条件。 我该如何解决它并通过问题?

seq +=2;//Race Condition: Singleton Member Field

【问题讨论】:

    标签: java spring spring-mvc fortify


    【解决方案1】:

    当我们在一个类中声明一个实例变量并在同一个类中的任何方法中使用该实例变量时,就会发生竞争条件。

     public class Test {  
     private boolean isRaceCondition;
     private String  myRaceCondition;
     public  void testMyMethod(){
     If(isRaceCondition){
         myRaceCondition= "Yes It is";
        }
       else{
           myRaceCondition= "No It is not";
       }
      }}
    

    以上代码在单线程环境下可以正常运行,但在多线程环境下,可能会有多个线程在同一段代码上工作,从而导致数据完整性问题。

    例如线程 T1 设置了 isRaceCondition=true 但在 T1 可以执行方法 testMyMethod() 之前,另一个线程 T2 重置了 isRaceCondition=false 所以现在当 T1 尝试执行 testMyMethod() 时它会看到 isRaceCondition为 false,它会设置 myRaceCondition= “No It is not”;

    要解决此问题,最简单的解决方案是 如果我们可以将初始值设置为变量,并且基本上它们是恒定的。

    private static final boolean isRaceCondition=True;
    private static final  String  myRaceCondition="Yes It is" ;
    

    如果我们不能设置初始值,我们使用volatile。这将确保变量的值在使用之前总是从内存中获取

    private static volatile boolean isRaceCondition;
    private static volatile  String  myRaceCondition;
    

    【讨论】:

      【解决方案2】:

      对于字符串和其他对象竞争条件,我们应该使用 AtomicReference 竞争条件。例如,私有 AtomicReference 名称并生成 setter 和 getter,类似地为用户定义的对象 AtomicReference 人并为此生成 setter 和 getter,您的竞争条件就解决了。

      p>

      【讨论】:

      • 私有 AtomicReference 名称;设置器和获取器
      • public AtomicReference getName() { 返回名称; } public void setName(AtomicReference name) { this.name = name; }
      • 用户定义对象的类似:
      • 私人 AtomicReference 人; public void setPerson(AtomicReference person) { this.person = person } public AtomicReference getPerson(){ return person; }
      • 请使用与您的答案相关的任何信息来编辑您的答案。所有的 cmets 都可以随时移除。
      【解决方案3】:

      尝试重新设计您的控制器以不将状态放入其中。 或者,您可以考虑使用 AtomicInteger

      AtomicInteger seq = new AtomicInteger();//Global variable
      
      @RequestMapping(value = "/agn/AP1W01A_004", method=RequestMethod.GET)
          public ModelAndView welcomeGrid(@RequestParam("payType")String payType){
              seq.set(gnRecService.findTheLastPK(payType));
              ModelAndView view = new ModelAndView(".agn.AP1W01A_004");
              return view;
          }
      
          public ModelAndView showPk() {
              final int localSeq = seq.addAndGet(2); 
              ModelAndView view = new ModelAndView(".agn.AP1W01A_004");
              view.addObject("seq",localSeq)
              return view;
          }
      

      【讨论】:

      • 如果变量seq是java.lang.String类型或者POJO,如何解决?谢谢
      • @HamiltonLin:您可以在 java.util.concurrent.atomic.AtomicReference 上阅读更多内容
      猜你喜欢
      • 1970-01-01
      • 2022-10-20
      • 1970-01-01
      • 2019-01-12
      • 2020-08-03
      • 1970-01-01
      • 1970-01-01
      • 2023-01-30
      • 1970-01-01
      相关资源
      最近更新 更多