分布式锁

网上也流传着很多分布试锁的实现方式,最近在读Redis in Action。里面也提到了分布式锁,我以前用redis实现锁,也只是实现一个简单的原子操作。并没用过太过复杂的方式,也没有实现阻塞。最近我想再写一个锁,不过当然跟一般的分布式锁不同。我的思路是:如果同一台机器多个线程判断资源有没有没占用,就没必要去redis上去查找了,直接查看本地标识。

import java.util.concurrent.ConcurrentHashMap;


public class MapLockSupport implements LockSupport {
    private ConcurrentHashMap<String,LockInfo> locksMap = new ConcurrentHashMap<>();

    public MapLockSupport() {
    }

    @Override
    public boolean tryLock(String resourceId,final long expire) {

        LockInfo lockInfo ;
        do {
           lockInfo = locksMap.putIfAbsent(resourceId, new LockInfo(resourceId, expire)); //返回null代表添加成功
           if (lockInfo == null) return true;
           try {
               lockInfo = locksMap.computeIfPresent(resourceId, (k, v) -> { // 判断是否超时
                   if (v.getExpireTimeStamp() < System.currentTimeMillis()) {
                       v.setExpire(expire);
                   } else {
                       throw new TimeoutException();
                   }
                   return v;
               });
           }catch (TimeoutException ex){
               return false;
           }
       }while(lockInfo == null);
        return true;
    }
    @Override
    public void releaseLock(String resouceId) {
        locksMap.remove(resouceId);
    }

    public static class TimeoutException extends RuntimeException{

    }

}

我用ConcurrentHashMap的原子方法,实现对本地资源的标识

package com.example.demo.lock;

import org.springframework.data.redis.core.RedisTemplate;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

public class RedisLockSupport implements  LockSupport {

    private RedisTemplate redisTemplate ;


    public RedisLockSupport(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public boolean tryLock(String resourceId, long expire) {
        if(redisTemplate.opsForValue().setIfAbsent(resourceId, expire, Duration.ofMillis(expire))){
            return true;
        }
       return false;
    }

    @Override
    public void releaseLock(String resourceId) {
        redisTemplate.delete(resourceId);
    }
}

redis是真正的分布式锁,我实现的很简单。

public class ComposeLockSupport implements LockSupport {
    private MapLockSupport mapLockSupport;
    private RedisLockSupport redisLockSupport;

    public ComposeLockSupport(MapLockSupport mapLockSupport, RedisLockSupport redisLockSupport) {
        this.mapLockSupport = mapLockSupport;
        this.redisLockSupport = redisLockSupport;
    }

    @Override
    public boolean tryLock(String resourceId, long expire) {
        if(mapLockSupport.tryLock(resourceId,expire)){
            if(redisLockSupport.tryLock(resourceId,expire)){
               return true;
            }else{
                mapLockSupport.releaseLock(resourceId);
            }
        }
        return false;
    }

    @Override
    public void releaseLock(String resourceId) {
        redisLockSupport.releaseLock(resourceId);
        mapLockSupport.releaseLock(resourceId);
    }
}

最后我将这两段代码组合在一起。以后整理

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值