必须设置失效时间,避免死锁。比如服务突然宕机,没有失效时间的话,节点永远不会被删除,那么其他线程都获取不到锁,死锁。
写入随机值,避免锁误删。比如失效时间是3S,业务一般处理只需要几十毫秒,某一次业务发生异常耗费了5S,再去解锁的时候,实际上此时自己设置的值已经过期删除了,此时的key是另一个线程加锁设置的,那么自己肯定不能把另一个线程加锁的值给删除,通过随机值value的匹配来避免。
写入值和设置失效时间必须是一个原子操作,保证加锁是原子的
set key value nx px 10000 (不能分几次命令操作,那样不是原子性的)
//因为key是不变的,每个线程加锁的时候,设置的值不一样,因此值在不断变化,如果步骤1和2不是原子的,可能获取的时候是一致
//的,判断的时候已经更改了。使用lua脚本实现:
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1]);
else
return 0;
end
publicclassMyRedisLockTest{publicstaticvoidmain(String[] args){for(int i =0; i <5; i++){//创建5个执行线程newMyThread("Thread-"+ i).start();}}staticclassMyThreadextendsThread{publicMyThread(String name){super(name);}@Overridepublicvoidrun(){
MyRedisLock.lock();try{
System.out.println("Thread "+ Thread.currentThread().getName()+" do something thing..."+newDate());
Thread.sleep(2000);}catch(InterruptedException e){
e.printStackTrace();}finally{
MyRedisLock.unLock();}}}}
输出(5个线程排队执行,锁生效了):
Thread Thread-0 do something thing...Sat Jun 15 23:14:52 CST 2019
Thread Thread-2 do something thing...Sat Jun 15 23:14:54 CST 2019
Thread Thread-1 do something thing...Sat Jun 15 23:14:56 CST 2019
Thread Thread-4 do something thing...Sat Jun 15 23:14:58 CST 2019
Thread Thread-3 do something thing...Sat Jun 15 23:15:00 CST 2019