锁在事务中的错误使用

 

 锁在事务中的错误使用
 
 
 错误示例:
 

@Override
    @Transactional(rollbackFor = Exception.class)
    public Item add(ItemDTO dto) throws Exception {

        //锁商品,防并发
        String lockKey = StringUtil.format(Constants.LOCK_ACTIVITY_PRODUCT, dto.getItemId());
        //加锁
        boolean isLock = redisClient.trylock(lockKey, 2 * 60);
        AssertUtil.isTrue(isLock, "该商品正在被处理中,请稍后再试");
        try {
            Item item = itemMapper.selectByItemId(dto.getItemId());
           if(item==null){
            ...
            itemMapper.insert(newItem);
           }else{
            ...
            itemMapper.updateItem(item);
           }
           return item;
        } finally {
   //释放锁,此时事务还未提交
            redisClient.unlock(lockKey);
        }
    }


 
 事务的范围大于锁的范围,锁释放的瞬间可能事务还没来的及提交,看源码:
 

 protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
   throws Throwable {

  // If the transaction attribute is null, the method is non-transactional.
  final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
  final PlatformTransactionManager tm = determineTransactionManager(txAttr);
  final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

  if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
   // Standard transaction demarcation with getTransaction and commit/rollback calls.
   TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
   Object retVal = null;
   try {
    // 执行完目标方法返回  (public Item add(ItemDTO dto) throws Exception)
    retVal = invocation.proceedWithInvocation();
   }
   catch (Throwable ex) {
    // target invocation exception
    completeTransactionAfterThrowing(txInfo, ex);
    throw ex;
   }
   finally {
    cleanupTransactionInfo(txInfo);
   }
   //提交事务
   commitTransactionAfterReturning(txInfo);
   return retVal;
  }

 

所以要保证线程安全锁应该加在事务之外

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值