yangcctv 发表于 2017-12-21 13:36:47

使用redis来实现分布式锁

public>private static final Logger LOG = LoggerFactory.getLogger(RedisDisLock.class);private transient Thread exclusiveOwnerThread;  String lockKey
="";  AtomicInteger waitToLock
=new AtomicInteger(0);public RedisDisLock(String lockKey){this.lockKey=CommonType.REDISKEY+lockKey;  }
  

public boolean tryLock(Jedis jedis) {  Thread thread
= Thread.currentThread();if(thread==this.getExclusiveOwnerThread()){return true;  }
  Long i
= jedis.setnx(lockKey, System.currentTimeMillis()+"");if(i.intValue()==1){  jedis.expire(lockKey, CommonType.LOCKEXPIRETIME);
  setExclusiveOwnerThread(thread);
return true;  }
else{//对于可能性非常低的死锁情况进行解锁  String initTime = jedis.get(lockKey);
  if(initTime==null){
  LOG.debug("initTime's value is null");
  return false;
  }
  long iniTime=0L;
  try{
  iniTime = Long.parseLong(initTime);
  }
  catch(NumberFormatException nfex){
  LOG.warn(nfex.getMessage());
  jedis.expire(lockKey, 1);
  return false;
  }
  if(((System.currentTimeMillis()-iniTime)/1000-CommonType.LOCKEXPIRETIME-1)>0){
  String oldTime = jedis.getSet(lockKey, System.currentTimeMillis()+"");//对于及其极端的情况,lock被线程1处理掉了,但是又被线程2getset新的值了,通过下一次调用trylock()方法处理
  if(oldTime==null){
  LOG.info("oldTime is null");
  return false;
  }
  if(initTime.equals(oldTime)){
  release(jedis);
  }
  }
  }
  return false;
  }
  

  public boolean tryLock(long timeout, TimeUnit unit,Jedis jedis) throws InterruptedException {
  long nanosTimeout = unit.toNanos(timeout);
  long lastTime = System.nanoTime();
  if(tryLock(jedis)){
  return true;
  }
  try{
  int waitLockers = waitToLock.getAndIncrement();
  if(waitLockers>=CommonType.WAITLOCKERS){
  LOG.debug("wait the lock' thread num is much,so return flase");
  return false;
  }
  for(;;){
  if(tryLock(jedis)){
  return true;
  }
  if (nanosTimeout <= 0){
  LOG.debug("getlock timeout");
  return false;
  }
  if(nanosTimeout>100000){
  LockSupport.parkNanos(100000);//中断100毫秒
  
                }
  long now = System.nanoTime();
  nanosTimeout -= now - lastTime;
  lastTime = now;
  if (nanosTimeout <= 0){
  LOG.debug("getlock timeout");
  return false;
  }
  if (Thread.interrupted()){
  throw new InterruptedException();
  }
  }
  }
  finally{
  waitToLock.decrementAndGet();
  }
  }
  

  public void unlock(Jedis jedis) {
  Thread thread = Thread.currentThread();
  if(thread==this.getExclusiveOwnerThread()){
  LOG.debug("unlock the thread {}",thread.getId());
  release(jedis);
  }
  }

  private void>  setExclusiveOwnerThread(null);
  jedis.del(lockKey);
  }
  /**
  * Sets the thread that currently owns exclusive access. A
  * <tt>null</tt> argument indicates that no thread owns access.
  * This method does not otherwise impose any synchronization or
  * <tt>volatile</tt> field accesses.
  */
  protected final void setExclusiveOwnerThread(Thread t) {
  exclusiveOwnerThread = t;
  }
  

  /**
  * Returns the thread last set by
  * <tt>setExclusiveOwnerThread</tt>, or <tt>null</tt> if never
  * set.This method does not otherwise impose any synchronization
  * or <tt>volatile</tt> field accesses.
  * @return the owner thread
  */
  protected final Thread getExclusiveOwnerThread() {
  return exclusiveOwnerThread;
  }
  
}
页: [1]
查看完整版本: 使用redis来实现分布式锁