synchronized (userId.toString().intern()) {
}
通过关键字进行枷锁,
userId.toString 底层还是进行了new String
即使userId相同 ,tostring后他的String类对象还是不一样的
所以加上一个intern()返回,让其在常量此中进行寻找,就可以保证 userId一直,tostring得到的方法也是一致的
要确保事务 提交完了,才能释放锁
Long userId = UserHolder.getUser().getId();
//要确保事务 提交完了,才能释放锁
synchronized (userId.toString().intern()) {
return creatVoucherOrder(voucherId);
}
}
@Transactional
public Result creatVoucherOrder(Long voucherId) {
Long userId = UserHolder.getUser().getId();
//判断用户是否已经抢过该优惠卷
Integer count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();
if (count > 0) {
return Result.fail("你已经抢过该优惠劵了");
}
boolean success = seckillVoucherService.update()
.setSql("stock=stock-1")
.eq("voucher_id", voucherId).gt("stock", 0).update();
if (!success) {
return Result.fail("已经抢完了");
}
VoucherOrder voucherOrder = new VoucherOrder();
long orderId = redisWorker.nextId("order");
voucherOrder.setVoucherId(orderId);
voucherOrder.setUserId(userId);
voucherOrder.setVoucherId(voucherId);
save(voucherOrder);
return Result.ok(voucherOrder);
}
//要确保事务 提交完了,才能释放锁
synchronized (userId.toString().intern()) {
// 事务 调用要由spring 得到该类的代理对象才能进行调用 而这个方法( return this.creatVoucherOrder(voucherId);) 使用this调用事务
//所以 该事务是不生效的
//生成一个代理对象 j
IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();
return proxy.creatVoucherOrder(voucherId);
}