package com.jarvis.cache.lock; /** * 基于Redis实现分布式锁 * @author jiayu.qiu */ public abstract class AbstractRedisLock implements ILock { protected abstract Long setnx(String key, String val); protected abstract void expire(String key, int expire); protected abstract String get(String key); protected abstract String getSet(String key, String newVal); private long serverTimeMillis() { return System.currentTimeMillis(); } private boolean isTimeExpired(String value) { return serverTimeMillis() > Long.parseLong(value); } protected abstract void del(String key); @Override public boolean tryLock(String key, int lockExpire) { long lockExpireTime=serverTimeMillis() + (lockExpire * 1000) + 1;// 锁超时时间 String lockExpireTimeStr=String.valueOf(lockExpireTime); if(setnx(key, lockExpireTimeStr).intValue() == 1) {// 获取到锁 try { expire(key, lockExpire); } catch(Throwable e) { } return true; } String oldValue=get(key); if(oldValue != null && isTimeExpired(oldValue)) { // lock is expired String oldValue2=getSet(key, lockExpireTimeStr); // getset is atomic // 但是走到这里时每个线程拿到的oldValue肯定不可能一样(因为getset是原子性的) // 假如拿到的oldValue依然是expired的,那么就说明拿到锁了 if(oldValue2 != null && isTimeExpired(oldValue2)) { return true; } } return false; } @Override public void unlock(String key) { try { del(key); } catch(Throwable e) { } } }