1 2 3 4 5 6 7 8 9 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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
   |  package io.binghe.concurrent.chapter19.service.impl;
  import io.binghe.concurrent.chapter19.service.RedisDistributeLock; import io.binghe.concurrent.chapter19.task.UpdateLockTimeoutTask; import io.binghe.concurrent.chapter19.utils.ThreadUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.stereotype.Service;
  import java.util.Collections; import java.util.concurrent.TimeUnit;
 
 
 
 
 
  @Service("redisDistributeLockV8") public class RedisDistributeLockV9Impl implements RedisDistributeLock {     @Autowired     private StringRedisTemplate stringRedisTemplate;     private ThreadLocal<String> threadLocal = new ThreadLocal<String>();     private ThreadLocal<Integer> threadLocalCount = new ThreadLocal<Integer>();     @Override     public boolean tryLock(String key, long timeout, TimeUnit unit) {         Boolean isLocked = false;         if (threadLocal.get() == null){             String currentThreadId = this.getCurrentThreadId();             threadLocal.set(currentThreadId);             isLocked = stringRedisTemplate.opsForValue().setIfAbsent(key, currentThreadId, timeout, unit);
                           if (!isLocked){                 for (;;){                     isLocked = stringRedisTemplate.opsForValue().setIfAbsent(key, currentThreadId, timeout, unit);                     if (isLocked){                         break;                     }                 }             }                          new Thread(new UpdateLockTimeoutTask(currentThreadId, stringRedisTemplate, key)).start();
          }else{             isLocked = true;         }                  if (isLocked){             Integer count = threadLocalCount.get() == null ? 0 : threadLocalCount.get();             threadLocalCount.set(++count);         }         return isLocked;     }
      @Override     public void releaseLock(String key) {                  String currentThreadId = stringRedisTemplate.opsForValue().get(key);         if (threadLocal.get().equals(currentThreadId)){             Integer count = threadLocalCount.get();             if (count == null || --count <= 0){                 stringRedisTemplate.delete(key);                                  threadLocal.remove();                 threadLocalCount.remove();
                                   String updateTimeThreadId = stringRedisTemplate.opsForValue().get(currentThreadId);                 if (updateTimeThreadId != null && !"".equals(updateTimeThreadId.trim())){                     Thread updateTimeThread = ThreadUtils.getThreadByThreadId(Long.parseLong(updateTimeThreadId));                     if (updateTimeThread != null){                                                  updateTimeThread.interrupt();                         stringRedisTemplate.delete(currentThreadId);
                      }                 }             }else {                 threadLocalCount.set(count);             }
          }     }
      private static final String LUA_UN_LOCK =             "if redis.call('get',KEYS[1]) == ARGV[1] then\n" +                     "    return redis.call('del',KEYS[1])\n" +                     "else\n" +                     "    return 0\n" +                     "end";
      public boolean releaseLock2(String key, String lockValue) {         DefaultRedisScript<String> redisScript = new DefaultRedisScript<>();         redisScript.setScriptText(LUA_UN_LOCK);         redisScript.setResultType(String.class);         Object result = stringRedisTemplate.execute(redisScript, Collections.singletonList(key), lockValue);         return "1".equals(result.toString());     }
      private String getCurrentThreadId(){         return String.valueOf(Thread.currentThread().getId());     } }
 
 
  |