当前位置: 首页>后端>正文

Java用Redisson分布式锁

一、代码

    @ApiOperation(value = "报名用户取消报名")
    @PutMapping("cancelAttend")
    public Result<Boolean> cancelAttend(@RequestParam Long attendId) {
        Long memberId = getMemberId();
        RLock redissonLock = redissonClient.getLock("cancelAttend:" + attendId);
        try {
            redissonLock.lock(5, TimeUnit.SECONDS);
            return Result.success(activityAttendService.cancelAttend(id, memberId));
        } finally {
            // 释放锁
            if (redissonLock.isLocked() && redissonLock.isHeldByCurrentThread()) {
                redissonLock.unlock();
            }
        }
    }

二、注意事项

2.1 lock key说明

本例代码锁用的key不是直接用报名IDattendId,而是在报名ID前加了一个字符串常量cancelAttend:,即:"cancelAttend:" + attendId。原因是可能还有其他方法也会用attendId加锁,比如报名核销方法。如果取消报名、报名核销都用attendId做为lock key,就会出现两个方法共用一个key的情况,所以才在前面加了一个字符串常量来做区分。

2.2 释放锁

释放锁不是直接调用redissonLock.unlock();,而是在释放锁之前加了一层判断。

  • redissonLock.isLocked():如果两个方法共用了一个lock key,就有出现key被第一个方法释放了,第二个方法又去释放,就会报错。

  • redissonLock.isHeldByCurrentThread():在分布式服务中,就只需要释放当前线程加的锁。当然也需要加上redissonLock.isLocked()

2.3 事务问题

加锁代码不要写在@Transactional事务里面,否则锁会失效,锁不住数据,还是会出现并发问题。可参考Redisson失效场景


https://www.xamrdz.com/backend/3gs1931811.html

相关文章: