分布式锁实现方案2、基于Redis的SET操作实现的分布式锁

继上一篇文章 分布式锁实现方案1、基于Redis的SETNX操作实现的分布式锁 实现方案之后,redis又提供了更加强大的set方法,可以解决分布式锁实现方案1中提到的缺陷,直接看代码

package com.alioo.lock;

import com.jd.jim.cli.Cluster;

import java.util.concurrent.TimeUnit;

/**
 * <pre>
 * 基于Redis的SET操作实现的分布式锁
 * </pre>
 *
 * @author [email protected]
 *
 */
public class RedisDistributedLock2 {

    private Cluster redis;

    // 锁的名字
    private String lockKey;

    private boolean locked;

    // 当前jvm内持有该锁的线程(if have one)
    private Thread exclusiveOwnerThread;

    /**
     *
     * @param redis
     * @param lockKey  lockKey
     * @throws java.io.IOException
     */
    public RedisDistributedLock2(Cluster redis, String lockKey ) {
        this.redis = redis;
        this.lockKey = lockKey;
    }

    /**
     * 阻塞式获取锁 ,不过有超时时间,超过了tryGetLockTime还未获取到锁将直接返回false
     *
     * @param tryGetLockTime
     * @param tryGetLockUnit
     * @return
     */
    protected boolean lock(long tryGetLockTime, TimeUnit tryGetLockUnit) {
        try {
            // 超时控制 的时间可以从本地获取, 因为这个和锁超时没有关系, 只是一段时间区间的控制
            long start = System.currentTimeMillis();
            long timeout = tryGetLockUnit.toMillis(tryGetLockTime);

            while (System.currentTimeMillis() - start < timeout) {
                long lockExpireTime = System.currentTimeMillis() + timeout + 1;//锁超时时间
                String stringOfLockExpireTime = String.valueOf(lockExpireTime);

               boolean flag= redis.set(lockKey, stringOfLockExpireTime, tryGetLockTime, tryGetLockUnit, false);
                if (flag) { // 获取到锁, 设置相关标识
                    locked = true;
                    exclusiveOwnerThread = Thread.currentThread();
                    return true;
                }
                Thread.sleep(5L);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return false;
    }


    /**
     * 非阻塞,立即返回是否获取到锁
     * @return
     */
    public boolean tryLock(long tryGetLockTime, TimeUnit tryGetLockUnit) {
        long timeout = tryGetLockUnit.toMillis(tryGetLockTime);
        long lockExpireTime = System.currentTimeMillis() + timeout + 1;//锁超时时间
        String stringOfLockExpireTime = String.valueOf(lockExpireTime);

        boolean flag= redis.set(lockKey, stringOfLockExpireTime, tryGetLockTime, tryGetLockUnit , false);
        if (flag) { // 获取到锁, 设置相关标识
            locked = true;
            exclusiveOwnerThread = Thread.currentThread();
            return true;
        }
        return false;
    }

    public boolean isLocked() {
        return locked;
    }

    /**
     * 释放锁
     */
    public void unlock() {
        // 检查当前线程是否持有锁
        if (Thread.currentThread() != exclusiveOwnerThread) {
            // 表明锁并非当前线程所持有,不应该由当前线程来释放锁
            System.out.println("锁并非当前线程所持有,放弃释放锁exclusiveOwnerThread:" + exclusiveOwnerThread + ",Thread.currentThread():" + Thread.currentThread() + ",lockKey" + lockKey);
            return;
        }

        redis.del(lockKey);
        exclusiveOwnerThread = null;
    }

}

猜你喜欢

转载自blog.csdn.net/hl_java/article/details/79132128