悲观锁与乐观锁

悲观锁

1、使用场景:

悲观锁可以作为分布式锁的一种实现方式,即你某些业务想在高并发的场景下仍被单机执行时,可以在业务代码执行前,先去获取某行数据的悲观锁,执行业务完成后释放锁(commit or rollback),当你还没有释放锁之前,如果有其他线程执行进来且要获取相同表相同行数据的悲观锁,肯定是获取失败的,会抛出异常,而不会去执行业务代码。

 

2、悲观锁的核心实现:

select id from table where ... for  update  nowait

  1. 此语句如果会把所有符合条件的行锁住,如果没有where条件会锁整张表,如果查询条件获取到的行数据为空,则不会锁住行数据;
  2. 一旦行数据被这样锁住了,如果获取悲观锁的当前事务还没有commit,那么下一个获取悲观锁的事务一定是失败的;
  3. 如果锁用完了,需要释放 (即事务的 commit 或 rollback ) 。mybatis框架会自动commit,即在获取完悲观锁以后立即就commit了,而没有等到业务执行完才 commit,在高并发时都能获取悲观锁成功。所以需要使用编称式事务来替代 @Transacional
  4. nowait表示:不会被阻塞,如果获取悲观锁失败,直接抛异常而不必等待。

 

3、测试1

测试环境:oracle数据库 + mybatis

释放悲观锁,需要执行 commit 。

4、测试2

 

5、代码实现

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

        TransactionStatus status = null;
        try {
            //开启编称式事务
            status = txManager.getTransaction(new DefaultTransactionDefinition());
            //获取悲观锁
            funcScheduleDefService.forUpdateNoWait(monthendConfirmDTO.getDid(), function, monthendConfirmDTO.getStatDate());
        } catch (Exception e) {
            //获取锁失败,回滚事务
            txManager.rollback(status);
            return null;
        }

        。。。添加悲观锁成功,执行业务逻辑


        //执行业务完成,提交事务,释放锁
        txManager.commit(status);
        

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值