处理系统中一个并发引起的bug
2016-03-07 13:52
344 查看
背景
之前系统在更新某条业务数据的状态时,并没有判断该数据的原来的状态,直接更新成了最新状态。这样如果有多线程来访问代码,会出现由于并发导致出现脏数据。简单举例
订单数据:
id | name | status |
---|---|---|
1 | 测试 | 1 |
业务场景:
当某个业务请求过来后,我们会把订单数据的status更新成2,表示订单完成,然后进行后续业务动作,产生一些正常的业务数据。错误的代码片段
Order order = db.getOrder(orderId); if (order.getStatus = 1) { //把订单状态更新为2 db.updateOrderStatus(2); }
这段代码是有问题的,如果两个线程同时都通过
order.getStatus=1这个判断,那么都会去更新数据状态,并且更新成功进入后续的流程,这样的话,就会产生一些不必要的数据,对系统和用户都带来了影响。
正确的代码片段
int count = db.updateOrderStatusWithOriginOrderStatus(1,2);
可以利用数据库,把原来的订单状态传递进去,当线程Thread1更新数据时,只有订单状态还是1的,才进行状态更新,一旦订单数据的状态已经不是1了,说明这条订单数据被其他的线程(这里假设是Thread2)捷足先登 的更新了。这个时候,Thread1应该return出去了,不要再做任何事情了。
备注:
当然也可以使用乐观锁来处理,使用version判断。原理其实跟我上面提到的方案差不多。相关文章推荐
- JSON 格式总结
- linux ps top 命令 VSZ,RSS,TTY,STAT, VIRT,RES,SHR,DATA的含义【转】
- NSObject的load和initialize方法
- 2085: [Poi2010]Hamsters hash+倍增floyd
- Shiro学习--Apache Shiro Architecture(Shiro架构)
- poj 1159 Palindrome 动态规划的三种解法
- Android应用架构之MVP实现
- Java异常体系结构
- javax.persistence.NonUniqueResultException: result returns more than one elements
- Hadoop op 1)
- 安全卫士第八天笔记
- 如何识别页面加载过程中出现的元素
- Block
- 使用C#向ACCESS中插入数据
- 使用RxBinding处理控件异步调用
- xamarin.forms 版本自动更新(针对android)
- hosts google
- MyBatis的学习总结六:Mybatis的缓存【参考】
- ZOJ3329
- oracle 新建表空间、用户