之前说的volatile,然后查资料的时候又看到了synchronize,突然想起来这玩意有同事直接加在service层的方法上,但好像并不是完全靠谱的。
因为之前也有用到过简单的分布式锁redission,然后redission是在service层方法里面上的锁,结果就导致数据库数据依然不一致(即锁没什么卵用)。
调用如下:
(1)req -> (2)web.method -> (3)service.method(开启事务) -> (4)redission lock(上锁) -> (5)执行业务 -> (6)redission unlock(放锁) -> (7)方法结束(事务提交) -> (8)返回数据;
一切看起来都这么美好,整条流程一气呵成。但是为何就没什么卵用呢??
原因在于:并发量较大的情况下,大量线程阻塞在 (3) -> (4) 当某线程放锁但未提交事务时(即 (6) -> (7)),另外一线程瞬间获取到了锁于是乎,,,锁就成了摆设,自然数据就出现了问题。
至于synchronize的话我虽然没怎么用过,但是个人感觉也会出现这种问题。尽管synchronize加在方法上面的,但是事务是AOP级别的,进入方法前就会开启,方法结束才会提交,异常就会回滚。
所以我一般简单的再web层就加锁了。。
说到这里也简单总结对于简单并发的处理:
1, 悲观方式:即每次都加锁,如redission(分布式锁) ReentrantLock(单体应用) 等。
2, 乐观方式:1 使用版本号version,但是需要数据表添加字段 ;
2 先修改数据,再查询数据,进行判断(一般先查后改) ;
悲观方式:可能造成线程大量挂起,接口拥堵,访问拒绝。
乐观方式:每次访问数据库,增加数据库压力,特别是在大量回滚操作时,数据库可能会歇菜.