redis simple implementation based on distributed lock

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/**
  * 主要用于在分布式环境下对于共享资源的操作进行锁定
  */
public class RedisLock {
 
     private RedisTemplate redisTemplate;
 
     //获取锁最长等待时间;10秒
     private static final long WAIT_TIME_OUT = 10 * 1000 ;
 
     //锁的过期时间;3秒
     private static final int LOCK_EXPIRE_TIME = 3 * 1000 ;
 
     public RedisLock(RedisTemplate redisTemplate) {
         this .redisTemplate = redisTemplate;
     }
 
     /**
      * 在一定的限定时间内 获取某一类资源或操作的锁
      *
      * @param key 键名(可以随便指定;一般为某一类资源或操作命名)
      * @return true or false
      */
     public Boolean lock(String key) throws InterruptedException {
         long timeOut = WAIT_TIME_OUT;
         while (timeOut > 0 ) {
             long expireTime = System.currentTimeMillis() + LOCK_EXPIRE_TIME;
             Boolean isExists = redisTemplate.boundValueOps(key).setIfAbsent(expireTime);
             if (isExists) { //获取锁成功,直接返回
                 return true ;
             }
 
             //获取锁失败,查看是否锁已经超时
             long oldExpireTime = ( long ) redisTemplate.boundValueOps(key).get();
             if (oldExpireTime < System.currentTimeMillis()) { //锁已经超时
                 //自行尝试解锁并获取锁
                 long newExpireTime = System.currentTimeMillis() + LOCK_EXPIRE_TIME;
                 long oldExpireTime2 = ( long ) redisTemplate.boundValueOps(key).getAndSet(newExpireTime);
                 if (oldExpireTime == oldExpireTime2) {
                     //没有被其它线程设置并获取,说明获取锁成功
                     return true ;
                 }
             }
 
             //沉睡随机几百毫秒再去尝试获取锁
             long sleepTime = ( long ) (Math.random() * 1000 );
             //递减等待获取锁的时间
             timeOut = timeOut - sleepTime;
 
             Thread.sleep(sleepTime);
         }
         return false ;
     }
 
     /**
      * 释放某一类资源或操作的锁
      *
      * @param key key 键名(与加锁时候的key要一致)
      */
     public void unlock(String key) {
         long expireTimeMillis = ( long ) redisTemplate.boundValueOps(key).get();
         if (System.currentTimeMillis() < expireTimeMillis) {
             //如果释放锁的时候没有超时才需要释放锁;不然这是可能被其它线程已经获取到的锁,不应该把其它线程获取到的锁给释放了
             redisTemplate.delete(key);
         }
     }
}
More technical information may concern: gzitcast

Guess you like

Origin www.cnblogs.com/heimaguangzhou/p/11412771.html