zoukankan      html  css  js  c++  java
  • 遇到线程安全问题的案例

    web项目中每个请求都是一个新的线程,如下代码,在不同的service层中操作相同的数据时,会出现线程安全问题。具体表现是:设定 sms初始值为10,smsUsed初始值为0;则两个请求分别同时访问test方法和testB方法时,两个方法中输出的结果显示:sms:9 smsUsed:1;按照正常的业务逻辑来说,当两个请求都完成后,sms应该为8,smsUsed为2。

    @Override
        @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
        public void test(){
            Long hid = 6L;
            Saler saler = salerDAO.getSalerBySid(hid);
            Long sms = saler.getSmsUnused();
            sms--;
            Long smsUsed = saler.getSmsUsed();
            smsUsed++;
            System.out.println("test ##### sms:"+ sms +" smsUsed:" + smsUsed);
            try {
                Thread.sleep(15000);
            }catch (Exception e) {
                throw new SelectNoFindException("test睡眠报错了",null);
            }
            salerDAO.updateSalerSms(hid, sms, smsUsed);
            System.out.println("test ##### sms:"+ sms +" smsUsed:" + smsUsed);
        }
    
        @Override
        @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
        public void testB(){
            Long hid = 6L;
            Saler saler = salerDAO.getSalerBySid(hid);
            Long sms = saler.getSmsUnused();
            sms--;
            Long smsUsed = saler.getSmsUsed();
            smsUsed++;
            salerDAO.updateSalerSms(hid, sms, smsUsed);
            System.out.println("testB ##### sms:"+ sms +" smsUsed:" + smsUsed);
        }
    View Code

    解决方案: 

      方案1.将两个方法合并成一个,在获取和修改共享数据时加锁。

      方案2.因为两个方法中修改共享数据的sql是相同的,所以可以使用数据库的行级锁(排它锁),在查询共享数据的sql语句后面加上 “for update”;

  • 相关阅读:
    有关Maven
    白盒测试(White-box Testing)
    Peer Review(同行评审)
    闰年测试(非法输入的判断)
    等价类划分的应用2
    等价类划分(Equivalence Class Partitioning)
    软件测试随堂笔记-1
    软件测试之注意事项
    软件测试的发展方向
    软件测试之白盒测试
  • 原文地址:https://www.cnblogs.com/zhlblogs/p/12674709.html
Copyright © 2011-2022 走看看