高并发问题,spring,JDBC
springmvc框架,我创建了50个线程并开启访问我的一个方法。方法是对一个字段读取并加1操作。isDelete这个字段的初始值是1,理想计算结果应该是51,但是结果却是6,很多个线程都是重复读写了。有经验的朋友告诉我这个应该怎么解决。
我如果用jdbc实现这种情况是这样做的。如下图2,可以解决这个问题,但是springmvc框架怎么解决这种问题???这个事物配置有什么关系吗?
图1:
图2:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(25)
暂不考虑、
另外,这个问题跟spring mvc没有一丁点关系。另外要实现并发控制,大致的过程应该是这样的 lock ... process business ... release_lock
乐观锁
你这先查询后,再更新,多个线程执行的时候肯定存在问题。比如同时10个线程执行select,虽然加了for update锁,在没有执行update之前,10个线程的select得到的结果都是一样的,所以这10个update的值都一样。
按照你的意思,直接执行update hospital set isDelete = isDelete + 1 where hospitalid = 1;就可以实现你的目标,这个不存在并发问题,因为update时DB已经上了锁了
select is_delete as isDelete from tablename where id=#{id} lock in share mode 这样就能保证每次查询的值都是上个线程修改过后的值。 我这样操作,就会得到理想的值。但是这个问题是我加的锁竟然是共享锁。
你这是无锁操作 想有序输出结果 肯定有问题啊,
回复
写的很清楚了:SERIALIZABLE。满足你的要求。
这个事物管理是不是名副其实的串行访问?这个注解实测可以的。
我上午测的时候忘记把锁去掉了,下午才发现,重新测了下,你的这个方法行不通。
你可以设计的时候,在这个表加一列值,vesion,
update tab set num = num +1 ,version = vesion+1
where id = xxx and version = current_version
,这样就会避免并发处理的问题了。
@Transactional(isolation = Isolation.SERIALIZABLE)
当年淘宝的某个BUG就是因为锁导致的。。。
回复
改改sql,update hostpital set isDelete = isDelete + 1,把事务扔给数据库去处理吧。
回复
你这个属于投机取巧的,我就是想模拟这个并发问题的。你恰巧把我模拟的并发场景弄没了。
回复
嘿嘿
回复
那个不是投机取巧,你自己写的代码有问题是因为没有加锁的原因,而他用这种sql是因为数据库执行这条sql的时候会默认加锁,所以不会出现你的情况
回复
是的,我懂了。现在要么加同步锁,要么用他说的+1操作,事物操作现在行不通。
update hostpital set isDelete = " +urlInt+ ", 这个地方多线程update会有问题吧,没有锁保护,结果以最后一个update的线程为准
JDBC我是用for update实现的。
这个可以的,msyql的更新操作自带排它锁,这样能避免并发问题。 也是一种好的ide
lock in share mode -- 共享锁 允许事务读取行
for update --排他锁 允许事务修改和更新行
共享锁:这里虽然是读取到了,但是数据可能不是你想要得到的,这里可以采取一种策略,表里加一标志列。
update set xxx where flag = false(表示未使用)
排他锁:这里不需要做任何处理,因为在select for update的时候必须等到其他事务提交里之后才能执行
排它锁吗?还是同步锁?
回复
同步锁
回复
可以的,排它锁和事物管理请问下你能给个思路吗?
确定不需要加锁嘛···