Java代码实现redis分布式锁

Java代码实现分布式锁

package com.msb.redis.lock;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.params.SetParams;

import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * 分布式锁的实现
 */
@Component
public class RedisDistLock implements Lock {
    
    

    private final static int LOCK_TIME = 5*1000;
    private final static String RS_DISTLOCK_NS = "tdln:";
    /*
     if redis.call('get',KEYS[1])==ARGV[1] then
        return redis.call('del', KEYS[1])
    else return 0 end
     */
    private final static String RELEASE_LOCK_LUA =
            "if redis.call('get',KEYS[1])==ARGV[1] then\n" +
                    "        return redis.call('del', KEYS[1])\n" +
                    "    else return 0 end";
    /*保存每个线程的独有的ID值*/
    private ThreadLocal<String> lockerId = new ThreadLocal<>();

    /*解决锁的重入*/
    private Thread ownerThread;
    private String lockName = "lock";

    @Autowired
    private JedisPool jedisPool;

    public String getLockName() {
    
    
        return lockName;
    }

    public void setLockName(String lockName) {
    
    
        this.lockName = lockName;
    }

    public Thread getOwnerThread() {
    
    
        return ownerThread;
    }

    public void setOwnerThread(Thread ownerThread) {
    
    
        this.ownerThread = ownerThread;
    }

    @Override
    public void lock() {
    
    
        while(!tryLock()){
    
    
            try {
    
    
                Thread.sleep(100);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
    
    
        throw new UnsupportedOperationException("不支持可中断获取锁!");
    }

    @Override
    public boolean tryLock() {
    
    
        Thread t = Thread.currentThread();
        if(ownerThread==t){
    
    /*说明本线程持有锁*/
            return true;
        }else if(ownerThread!=null){
    
    /*本进程里有其他线程持有分布式锁*/
            return false;
        }
        Jedis jedis = null;
        try {
    
    
            String id = UUID.randomUUID().toString();
            SetParams params = new SetParams();
            params.px(LOCK_TIME);
            params.nx();
            synchronized (this){
    
    /*线程们,本地抢锁*/
                if((ownerThread==null)&&
                "OK".equals(jedis.set(RS_DISTLOCK_NS+lockName,id,params))){
    
    
                    lockerId.set(id);
                    setOwnerThread(t);
                    return true;
                }else{
    
    
                    return false;
                }
            }
        } catch (Exception e) {
    
    
            throw new RuntimeException("分布式锁尝试加锁失败!");
        } finally {
    
    
            jedis.close();
        }
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
    
    
        throw new UnsupportedOperationException("不支持等待尝试获取锁!");
    }

    @Override
    public void unlock() {
    
    
        if(ownerThread!=Thread.currentThread()) {
    
    
            throw new RuntimeException("试图释放无所有权的锁!");
        }
        Jedis jedis = null;
        try {
    
    
            jedis = jedisPool.getResource();
            Long result = (Long)jedis.eval(RELEASE_LOCK_LUA,
                    Arrays.asList(RS_DISTLOCK_NS+lockName),
                    Arrays.asList(lockerId.get()));
            if(result.longValue()!=0L){
    
    
                System.out.println("Redis上的锁已释放!");
            }else{
    
    
                System.out.println("Redis上的锁释放失败!");
            }
        } catch (Exception e) {
    
    
            throw new RuntimeException("释放锁失败!",e);
        } finally {
    
    
            if(jedis!=null) jedis.close();
            lockerId.remove();
            setOwnerThread(null);
            System.out.println("本地锁所有权已释放!");
        }
    }

    @Override
    public Condition newCondition() {
    
    
        throw new UnsupportedOperationException("不支持等待通知操作!");
    }

}


猜你喜欢

转载自blog.csdn.net/a772304419/article/details/130568195