简单解锁 之 锁 的简单运用,单机锁 和 分布式锁

总结:锁分很多种,说起来都可怕,有些我自己都不是很清楚 具体可以参考  https://github.com/redisson/redisson/wiki/8.-%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E5%92%8C%E5%90%8C%E6%AD%A5%E5%99%A8

           我这里主要讲一下

            单机 : 常用的 锁  synchronized(一个对象持有 又可以 Class 持有)class 其实也是 Class 的一个对象 出异常主动释放 虚拟机自动

                         ReentrantLock  不会主动释放 需要自己手动释放 具体玩法自行百度  他们都是可重入(就是说同一个线程可以重复获取锁,内部维护了一个计数器)

           多机:有基于 redis ,zk,mysql  等 实现的。

          使用场景:公众号 access_token(一天调用次数有限,每次刷新的有效期2小时 老的token 还有5分钟的平滑期) 刷新 如果同时刷新 保存的又不是最新的 这样就会出问题

          前后端分离(几秒内只允许用户操作一次,多次直接不予处理),防止 表单重复提交(在传统的web项目中,防止重复提交,通常做法是:进入保存页面,后端生成一个唯一的提交令牌(uuid),并存储在服务端。页面提交请求携带这个提交令牌,后端验证并在第一次验证后删除该令牌,保证提交请求的唯 一性,前端 disable ,当然还可以mysql 唯一索引键,直接捕获副本异常(不推荐))

         话不多说redis 分布式锁如下:核心代码如下 

    

@Around("@annotation(com.example.demo.annotation.NoRepeatSubmit)")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
NoRepeatSubmit noRepeatSubmit = method.getAnnotation(NoRepeatSubmit.class);
int lockSeconds = noRepeatSubmit.lockTime();

HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
Assert.notNull(request, "request can not null");
   //此处可以用token或者JSessionId 还可以考虑 ip+请求参数+User-Agent 合起来md5 
    String token = request.getHeader("Authorization");
String path = request.getServletPath();
String key = getKey(token, path);
String clientId = getClientId();

boolean isSuccess = redisLock.tryLock(key, clientId, lockSeconds);
LOGGER.info("tryLock key = [{}], clientId = [{}]", key, clientId);

if (isSuccess) {
LOGGER.info("tryLock success, key = [{}], clientId = [{}]", key, clientId);
// 获取锁成功
Object result;

try {
// 执行进程
result = pjp.proceed();
} finally {
// 解锁
redisLock.releaseLock(key, clientId);
LOGGER.info("releaseLock success, key = [{}], clientId = [{}]", key, clientId);
}

return result;

} else {
// 获取锁失败,认为是重复提交的请求
LOGGER.info("tryLock fail, key = [{}]", key);
return new RepeatSubmitException("重复请求,请稍后再试");
}

      

 

          

转载于:https://www.cnblogs.com/lyc88/articles/11009543.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值