三种情况会导致jvm本地锁失效

一、业务对象或锁对象是多例的情况下

原因:业务中一般使用的lock对象锁,lock锁的范围是针对同一个对象里面不同的线程,也就是说,jvm锁是对象锁,对象之间锁不共用

解决方案:保证业务对象和锁对象是单例

二、在使用了spring事物注解的情况下(不单是jvm锁,大部分锁实现都会出现这个问题)

原因:spring事务是基于aop的方式实现的,是包裹着整个方法的(包括锁),事务不在锁的范围内,很容易出现并发执行的时候,a方法的事务还没提交上去,b事务就读了数据库的旧值。

举个例子:

代理类中的方法实际代码是这样的 :

a事务还没提交,b事务就读取了数据库的旧值(流程图):

解决方案:

第一种: 用显示事务,将事务放在锁范围里面

第二种: 事务隔离级别改为读未提交(不推荐)

第三种: 再套一层方法,在外层方法使用锁

第四种: 最优雅的解决方法,将锁封装成注解的形式,并把优先级设置成比事务注解低

三、在服务集群的情况下

原因:服务都不一样了,锁和对象自然也不一样(就和第一个情况下的环境一样)

解决方法:利用mysql的排他锁机制,将所有业务sql集中成一条sql(以上三种问题都能解决,但是不灵活,只能在业务允许的情况下使用)

总结

     综上所述,我们可以发现jvm锁只适合在单体项目中并且业务需求简单的情况下使用,所以有条件还是使用分布式锁吧。

2.一个sgl语句:更新数量时判断解决:解决了上面三个锁失效的问题,但是它是表级锁,这种是不能接受的,我要买多种商品结果你把表锁了,整张表都不能并发了、性能肯定就是不行的,最好使用行级锁。
问题:
1 锁范围问题:是表级锁还是行级锁
2.同一个商品有多条库存记录:仓库有多个、商品ID是一个,可以根据算法减库存、一个sql语句做不到
3.无法记录库存变化前后的状态

使用一个SQL语句时的优缺点

优点:一个sgl语句:更新数量时判断解决:解决了上面三个锁失效的问题

缺点:

1 锁范围问题:是表级锁还是行级锁
2.同一个商品有多条库存记录:仓库有多个、商品ID是一个,可以根据算法减库存、一个sql语句做不到
3.无法记录库存变化前后的状态

悲观锁的范围:表级锁还是行级锁?

我们有一张数据库表:里面有三条数据,商品1001分别在北京仓和上海仓、商品1002在深圳仓

我们首先模拟A用户开启事物、更新1001商品,让库存减1

如上图所示:此时2条数据更新成功,但是事物还没提交;

然后使模拟B用户开启事物、更新1002商品,让库存减1

此时我们就验证了mysql是表级锁

我们使用:commit 提交事物;或者ROLLBACK回滚事物;用户B的更新动作才会成功

很显然,一个sgl语句:更新数量时判断解决:解决了上面三个锁失效的问题,但是它是表级锁,这种是不能接受的,我要买多种商品结果你把表锁了,整张表都不能并发了、性能肯定就是不行的,最好使用行级锁。

mysql悲观锁中如何使用行级锁:

1、锁的查询或者与新条件必须是索引字段

2、查询或者更新条件必须是具体值;使用 =、in,不能使用like 、!=

我们在product_code字段上新建索引、然后重复上面步骤、发现是可以的、结果是行级锁、用户A和用户B执行更新互不影响;

注意:使用行级锁必须满足以上两个条件

悲观锁:select ... for update 

mysq使用乐观锁实现超卖

mysql乐观锁:借助时间戳、或者version版本号实现,需要依赖CAS这种机制

首先需要在表中增肌version字段,如下:

先查询:select * from distributed_lock where product_code = 1001

查询到的数据为2条、我们就取id为1的

此时product_code = 1001,id = 1 的商品的version为0,stock_count = 4997

我们执行修改动作

update distributed_lock set stock_count = stock_count-1,version = version+1 where id = 1 and version = 0,如果修改之间被用户B修改了、用户A修改成功影响的行数为0,此时我们会做重试的机制、直到它修改成功影响的行数变为1.

mysq!锁总结


性能:一个sql>悲观锁>jvm锁>乐观锁

如果追求极致性能、业务场景简单并且不需要记录数据前后变化的情况下。
        优先选择:一个sql!
如果写并发量较低(多读),争抢不是很激烈的情况下优先选择:乐观锁

如果写并发量较高,一般会经常冲突,此时选择乐观锁的话,会导致业务代码不间断的重试
优先选择:mysql悲观锁

不推荐ivm本地锁。

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值