redis实现分布式可重入锁
利用redis可以实现分布式锁,demo如下:
/**
* 保存每个线程独有的token
*/
private static ThreadLocal<String> tokenMap = new ThreadLocal<>(); /**
* redis实现分布式可重入锁,并不保证在过期时间内完成锁定内的任务,需根据业务逻辑合理分配seconds
*
* @param lock
* 锁的名称
* @param seconds
* 锁定时间,单位 秒
* token
* 对于同一个lock,相同的token可以再次获取该锁,不相同的token线程需等待到unlock之后才能获取
* @return
*/
public boolean lock(final String lock,final int seconds) {
// @param token 对于同一个lock,相同的token可以再次获取该锁,不相同的token线程需等待到unlock之后才能获取
String token = tokenMap.get();
if (StringUtil.isBlank(token)) {
token = UUIDGenerator.getUUID();
tokenMap.set(token);
}
boolean flag = false;
Jedis client = null;
try {
client = jedisPool.getResource();
String ret = client.set(lock, token, "NX", "EX", seconds);
if (ret == null) {// 该lock的锁已经存在
// String origToken = client.get(lock);// 即使lock已经过期也可以
31 // if (token.equals(origToken)||origToken==null) {// token相同默认为同一线程,所以token应该尽量长且随机,保证不同线程的该值不相同
32 // ret = client.set(lock, token, "NX", "EX", seconds);//
33 // if ("OK".equalsIgnoreCase(ret))
34 // flag = true;
35 // }
ret=client.cas(lock,origToken,token,seconds);
if("OK".equalsIgnoreCase(ret)){
flag=true;
}
} else if ("OK".equalsIgnoreCase(ret))
flag = true;
} catch (Exception e) {
logger.error(" lock{} 失败");
throw new RedisException(e);
} finally {
if (client != null)
client.close();
}
return flag;
} /**
* redis可以保证lua中的键的原子操作 unlock:lock调用完之后需unlock,否则需等待lock自动过期
*
* @param lock
* token
* 只有线程已经获取了该锁才能释放它(token相同表示已获取)
*/
public void unlock(final String lock) {
Jedis client = null;
final String token = tokenMap.get();
if (StringUtil.isBlank(token))
return;
try {
client = jedisPool.getResource();
final String script = "if redis.call(\"get\",\"" + lock + "\") == \"" + token + "\"then return redis.call(\"del\",\"" + lock + "\") else return 0 end ";
client.eval(script);
} catch (Exception e) {
logger.error(" unlock{} 失败");
throw new RedisException(e);
} finally {
if (client != null)
client.close();
} } public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
final RedisUtil redis = ctx.getBean(RedisUtil.class);
for (int i = 0; i < 100; i++) {
new Thread(new Runnable() {
String key = "cheng"; @Override
public void run() {
boolean lock = redis.lock(key, 30);
System.out.print(lock + "-"); }
}).start();
;
}
// redis.unlock(key);
// ctx.close();
}
运行main方法:
结果:true-false-......false-
redis实现分布式可重入锁的更多相关文章
- Springboot基于Redisson实现Redis分布式可重入锁【案例到源码分析】
一.前言 我们在实现使用Redis实现分布式锁,最开始一般使用SET resource-name anystring NX EX max-lock-time进行加锁,使用Lua脚本保证原子性进行实现释 ...
- Golang可重入锁的实现
Golang可重入锁的实现 项目中遇到了可重入锁的需求和实现,具体记录下. 什么是可重入锁 我们平时说的分布式锁,一般指的是在不同服务器上的多个线程中,只有一个线程能抢到一个锁,从而执行一个任务.而我 ...
- Redis分布式锁—Redisson+RLock可重入锁实现篇
前言 平时的工作中,由于生产环境中的项目是需要部署在多台服务器中的,所以经常会面临解决分布式场景下数据一致性的问题,那么就需要引入分布式锁来解决这一问题. 针对分布式锁的实现,目前比较常用的就如下几种 ...
- redis分布式锁-可重入锁
redis分布式锁-可重入锁 上篇redis实现的分布式锁,有一个问题,它不可重入. 所谓不可重入锁,即若当前线程执行某个方法已经获取了该锁,那么在方法中尝试再次获取锁时,就会获取不到被阻塞. 同一个 ...
- redis实现分布式锁需要考虑的因素以及可重入锁实现
死锁 错误例子 解决方式 防止死锁 通过设置超时时间 不要使用setnx key expire 20 不能保证原子性 如果setnx程序就挂了 没有执行expire就死锁了 reidis2 ...
- 【分布式锁】06-Zookeeper实现分布式锁:可重入锁源码分析
前言 前面已经讲解了Redis的客户端Redission是怎么实现分布式锁的,大多都深入到源码级别. 在分布式系统中,常见的分布式锁实现方案还有Zookeeper,接下来会深入研究Zookeeper是 ...
- Redisson 分布式锁源码 01:可重入锁加锁
前言 相信小伙伴都是使用分布式服务,那一定绕不开分布式服务中数据并发更新问题! 单系统很容易想到 Java 的各种锁,像 synchronize.ReentrantLock 等等等,那分布式系统如何处 ...
- ZooKeeper 分布式锁 Curator 源码 01:可重入锁
前言 一般工作中常用的分布式锁,就是基于 Redis 和 ZooKeeper,前面已经介绍完了 Redisson 锁相关的源码,下面一起看看基于 ZooKeeper 的锁.也就是 Curator 这个 ...
- Redisson分布式锁学习总结:可重入锁 RedissonLock#lock 获取锁源码分析
原文:Redisson分布式锁学习总结:可重入锁 RedissonLock#lock 获取锁源码分析 一.RedissonLock#lock 源码分析 1.根据锁key计算出 slot,一个slot对 ...
随机推荐
- HTTP 2 新特性
HTTP 2 新特性 HTTP/2 不是彻底的重写http协议,HTTP methods,status codes 和 语义化都是相同的,并且它应该使用和HTTP/1.x 相同的api 表示协议. H ...
- iOS 视频直播弹幕的实现
弹幕,并不是一个多么复杂的功能. 1.弹幕的实现性分析 首先,从视觉上明确当前弹幕所具有的功能 从屏幕右侧滑入左侧,直至完全消失 不管是长的弹幕,还是短的弹幕,速度一致(可能有的需求是依据弹幕长度,调 ...
- win10下Python3.6安装、配置以及pip安装包教程
0.目录 1.前言 2.安装python 3.使用pip下载.安装包 3.1 安装Scrapy 3.2 安装PyQt 3.3 同时安装多个包 3.4 pip的常用命令 1.前言 之前在电脑上安装了py ...
- JS 中对变量类型的五种判断方法
5种基本数据类型:undefined.null.boolean.unmber.string 复杂数据类型:object. object:array.function.date等 方法一:使用typeo ...
- 10.0.0.55_12-16训练赛部分writeup
0x1 - MISC MISC100 一张帅行的照片 目测是图片隐写,但是binwalk并没有出来,应该是对文件头进行了修改 010editor查看一下,发现在jpg文件尾之后还有大量的数据 而且在灰 ...
- 1.python的安装
1.python 安装实验所用为系统自带,退出为exit() 或ctrl +D命令 2.一般装pyhton2.7 ,3.5的版本有更多特效.不用在版本上太多纠结.python官网https://www ...
- Spring Boot-------JPA基础及查询规则
JPA基础及查询规则 JPA JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数 ...
- Eclipse 使用小结
代码智能提示 Java智能提示 Window -> Preferences -> Java -> Editor -> Content Assist -> Auto Act ...
- java集合框架(Collections Framework)
*/ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...
- HBase:Shell
HBase shell commands As told in HBase introduction, HBase provides Extensible jruby-based (JIRB) she ...