redis锁机制介绍与实例
1悲观锁
执行操作前假设当前的操作肯定(或有很大几率)会被打断(悲观)。基于这个假设,我们在做操作前就会把相关资源锁定,不允许自己执行期间有其他操作干扰。
Redis不支持悲观锁。Redis作为缓存服务器使用时,以读操作为主,很少写操作,相应的操作被打断的几率较少。不采用悲观锁是为了防止降低性能。
2乐观锁
执行操作前假设当前操作不会被打断(乐观)。基于这个假设,我们在做操作前不会锁定资源,万一发生了其他操作的干扰,那么本次操作将被放弃。
3.Redis中的锁策略
Redis采用了乐观锁策略(通过watch操作)。乐观锁支持读操作,适用于多读少写的情况!
在事务中,可以通过watch命令来加锁;使用UNWATCH可以取消加锁;
如果在事务之前,执行了WATCH(加锁),那么执行EXEC命令或DISCARD命令后,锁对自动释放,即不需要再执行UNWATCH了
例子
redis锁工具类
packagecom.fly.lock;
importredis.clients.jedis.Jedis;
importredis.clients.jedis.JedisPool;
importredis.clients.jedis.JedisPoolConfig;
publicclassRedisLock{
//初始化redis池
privatestaticJedisPoolConfigconfig;
privatestaticJedisPoolpool;
static{
config=newJedisPoolConfig();
config.setMaxTotal(30);
config.setMaxIdle(10);
pool=newJedisPool(config,"192.168.233.200",6379);
}
/**
*给target上锁
*@paramtarget
**/
publicstaticvoidlock(Objecttarget){
//获取jedis
Jedisjedis=pool.getResource();
//result接收setnx的返回值,初始值为0
Longresult=0L;
while(result<1){
//如果target在redis中已经存在,则返回0;否则,在redis中设置target键值对,并返回1
result=jedis.setnx(target.getClass().getName()+target.hashCode(),Thread.currentThread().getName());
}
jedis.close();
}
/**
*给target解锁
*@paramtarget
**/
publicstaticvoidunLock(Objecttarget){
Jedisjedis=pool.getResource();
//删除redis中target对象的键值对
Longdel=jedis.del(target.getClass().getName()+target.hashCode());
jedis.close();
}
/**
*尝试给target上锁,如果锁成功返回true,如果锁失败返回false
*@paramtarget
*@return
**/
publicstaticbooleantryLock(Objecttarget){
Jedisjedis=pool.getResource();
Longrow=jedis.setnx(target.getClass().getName()+target.hashCode(),"true");
jedis.close();
if(row>0){
returntrue;
}
returnfalse;
}
}
测试类
packagecom.fly.test;
importcom.fly.lock.RedisLock;
classTask{
publicvoiddoTask(){
//上锁
RedisLock.lock(this);
System.out.println("当前线程:"+Thread.currentThread().getName());
System.out.println("开始执行:"+this.hashCode());
try{
System.out.println("doing...");
Thread.sleep(2000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
System.out.println("完成:"+this.hashCode());
//解锁
RedisLock.unLock(this);
}
}
publicclassDemo{
publicstaticvoidmain(String[]args){
Tasktask=newTask();
Thread[]threads=newThread[5];
for(Threadthread:threads){
thread=newThread(()->{
task.doTask();
});
thread.start();
}
}
}
输出结果:
----------------------------------------------
当前线程:Thread-0
开始执行:2081499965
doing...
完成:2081499965
----------------------------------------------
当前线程:Thread-2
开始执行:2081499965
doing...
完成:2081499965
----------------------------------------------
当前线程:Thread-1
开始执行:2081499965
doing...
完成:2081499965
----------------------------------------------
当前线程:Thread-4
开始执行:2081499965
doing...
完成:2081499965
----------------------------------------------
当前线程:Thread-3
开始执行:2081499965
doing...
完成:2081499965
去掉redis锁后,执行结果:
----------------------------------------------
----------------------------------------------
当前线程:Thread-2
开始执行:1926683415
----------------------------------------------
当前线程:Thread-1
doing...
当前线程:Thread-0
----------------------------------------------
当前线程:Thread-3
开始执行:1926683415
doing...
开始执行:1926683415
doing...
----------------------------------------------
开始执行:1926683415
doing...
当前线程:Thread-4
开始执行:1926683415
doing...
完成:1926683415
完成:1926683415
完成:1926683415
完成:1926683415
完成:1926683415
Processfinishedwithexitcode0
利用redis这个性质,可以实现分布式锁,当然设计一定复杂一些!
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对毛票票的支持。如果你想了解更多相关内容请查看下面相关链接