使用redis實現分佈式鎖-實現

上一篇也說到了使用redis怎樣實現鎖機制,其實無外乎就如下幾個點:redis

1.如何保證上鎖和解鎖同爲本身的鎖而不是其餘線程的鎖?

2.上鎖以後線程中止,怎麼解鎖?

3.多個線程競爭同一個鎖,如何保證只有一個線程搶到?

4.沒有搶到鎖的線程要怎麼操做?

首先咱們選用 RedisTemplate 來操做Redis,2.1.0 以上的版本,有了setIfAbsent ,意思是:若是鍵不存在則新增,存在則不改變已經有的值。ide

@Service
public class RedisService {

    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 若是鍵不存在則新增,存在則不改變已經有的值。
     * expireTime :單位爲秒
     *
     * @return; 新增成功返回 true,反之則 false
     */
    public Boolean setIfAbsent(final String key, Object value, Long expireTime) {
        return redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.SECONDS);
    }

}

沒有工具類,就引入了@Service註解,核心就 getLock 和 unLock 兩個,相信你看完就能本身回答上面那四個問題了。工具

**
 * @ClassName : RedisLock
 * @Author : Yanqiang
 * @Date : 2019/9/10
 * @Description :redis鎖實現
 */
@Service
public class RedisLock {

    @Resource
    RedisService redisService;

    /**
     * 使用 redis獲取鎖
     * key : key
     * value   : value
     * expireTime  : key value在redis中的過時時間,防止死鎖
     * timeOut : 獲取鎖的過時時間
     *
     * @return: 返回value,以便在解鎖的時候,判斷當前鎖是否爲此線程的鎖
     */
    private String getLock(String key, String value, Long expireTime, Long timeOut) {
        //在timeOut內若是獲取不到鎖會一直嘗試重試(借鑑自旋的思想),獲取鎖的時間超過timeOut,就返回null,
        while (timeOut - System.currentTimeMillis() > 0) {
            //setIfAbsent:若是不存在就新增,存在則不作任何操做
            Boolean lock = redisService.setIfAbsent("lock:" + key, value, expireTime);
            if (lock) {
                return value;
            }
        }
        return null;
    }

    /**
     * 解鎖
     * key : key
     * value   : value
     */
    public Boolean unLock(String key, String value) {
        key = "lock:" + key;
        //讀取value值,判斷是否爲當前線程的鎖
        if (redisService.get(key).toString().equals(value)) {
            return redisService.remove(key);
        }
        return false;
    }

    /**
     * 次數
     */
    int n = 0;

    /**
     * 測試鎖demo
     */
    public void seckill() {
        // 返回鎖的value值,供釋放鎖時候進行判斷
        String threadName = Thread.currentThread().getName();
        String key = "resource";
        String identifier = getLock(key, threadName, 5L, System.currentTimeMillis() + 10000);

        if (identifier != null) {
            System.out.println(identifier + " 得到了鎖");
            System.out.println(n++);
            Boolean unLock = unLock(key, identifier);
            if (unLock) {
                System.out.println(identifier + " 釋放了鎖");
            } else {
                System.out.println(key + " 釋放鎖失敗 --error");
            }
        } else {
            System.out.println(key + " 沒有得到到鎖 --error");
        }
        System.out.println("=====================================");
    }
}
相關文章
相關標籤/搜索