0
点赞
收藏
分享

微信扫一扫

redis实现分布式锁

    使用redis实现一个简单的分布式锁,主要是使用redis的setnx和getset方法进行实现。

加锁:

     1.使用setnx设置值:

            key:为需要加锁的锁名  value 为 当前时间+锁的超时时间

            成功:

                返回true 和锁的超时时间

            失败:

                根据key获取超时时间

                      为空:说明该锁已经释放了,重新获取锁

                      不为空:

                                  判断锁是否已经超时

                                  超时:

                                        使用getset进行获取锁

                                              如果返回的值和上一步获取的锁的超时时间一样说明获取锁,(当不一样时可能会导致将上一个线程设置的锁的超时时间进行修改,应该影响不大。)

                                  没有超时:

                                        说明锁被别的线程持有。

解锁:

     解锁只可解除自己加的锁:

     先获取锁的超时时间

         为空:说明该锁已经不存在了

        不为空:  根据加锁得到的返回值 和解锁得到的时间进行比较,如果一样说明是自己加的锁。

代码:

com.huan.redis.redis_lock.Lock.LockResult ---> 获取锁之后的返回值   用于判断是否获取锁 和 放入锁中的内容

com.huan.redis.redis_lock.Lock                    ---> 锁的接口

com.huan.redis.redis_lock.RedisLock           ---> 锁的具体实现

锁的接口

package com.huan.redis.redis_lock;

/**
* 锁的接口
*
* @描述
* @作者 huan
* @时间 2016年10月30日 - 下午2:31:10
*/
public interface Lock {

LockResult lock(String lockName);

/**
* 获取锁
*
* @param lockName
* 需要上那一把锁
* @param lockTime
* 需要使用所的时间
* @param waitTime
* 当waitTime这个时间之内还没有获取到锁就退出获取锁
*/
LockResult lock(String lockName, long lockTime, long waitTime);

/**
* 释放锁
*
* @param lockName
*/
void unLock(String lockName, LockResult result);

static class LockResult {
private boolean lock;
private long info;

public LockResult(boolean lock, long info) {
super();
this.lock = lock;
this.info = info;
}

public boolean isLock() {
return lock;
}

public void setLock(boolean lock) {
this.lock = lock;
}

public long getInfo() {
return info;
}

public void setInfo(long info) {
this.info = info;
}
}
}

 锁的具体实现

package com.huan.redis.redis_lock;

import java.text.SimpleDateFormat;
import java.util.Date;

import redis.clients.jedis.Jedis;

/**
* 使用redis实现分布式锁
*
* @描述
* @作者 huan
* @时间 2016年10月30日 - 下午2:39:11
*/
public class RedisLock implements Lock {

private Jedis jedis;

public RedisLock(Jedis jedis) {
this.jedis = jedis;
}

@Override
public LockResult lock(String lockName, long lockTime, long waitTime) {
long now = System.currentTimeMillis();
LockResult lockResult = new LockResult(false, 0);
while (System.currentTimeMillis() - now <= waitTime) { // 重试 直到超时
long needLockTime = System.currentTimeMillis() + lockTime;
if (jedis.setnx("lock:" + lockName, String.valueOf(needLockTime)) == 1) { // 获取锁
System.out.println(Thread.currentThread().getName() + " : 获取锁1.." + new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date()));
lockResult = new LockResult(true, needLockTime);
return lockResult;
}
String oldTime = jedis.get("lock:" + lockName); // 如果没有获取锁,则获取锁的持有时间
if (null != oldTime) { // 锁还在
if (System.currentTimeMillis() - Long.parseLong(oldTime) > 0) { // 锁已经超时
needLockTime = System.currentTimeMillis() + lockTime; // 计算新的锁超时时间
String _oldLockTime = jedis.getSet("lock:" + lockName, String.valueOf(needLockTime)); // 设置锁的超时时间
if (null != oldTime && _oldLockTime != null && oldTime.equals(_oldLockTime)) { // 获取锁
System.out.println(Thread.currentThread().getName() + " : 获取锁2.." + new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date()));
lockResult = new LockResult(true, needLockTime);
return lockResult;
} else {
// System.out.println("另外的线程释放锁.");
}
}
// System.out.println(Thread.currentThread().getName() + " : 尝试获取锁..");
} else { // 另外的线程释放锁,需要重新获取锁
needLockTime = System.currentTimeMillis() + lockTime; // 计算新的锁超时时间
if (jedis.setnx("lock:" + lockName, String.valueOf(needLockTime)) == 1) {
System.out.println(Thread.currentThread().getName() + " : 获取锁3.." + new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date()));
lockResult = new LockResult(true, needLockTime);
return lockResult;
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}

return lockResult;
}

@Override
public void unLock(String lockName, LockResult lockResult) {
String oldTime = jedis.get("lock:" + lockName);
if (null != oldTime && lockResult.isLock() && lockResult.getInfo() == Long.parseLong(oldTime)) {
System.out.println(Thread.currentThread().getName() + " 释放锁.." + new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date()));
jedis.del("lock:" + lockName);
} else {
if (0 == lockResult.getInfo()) {
System.out.println(Thread.currentThread().getName() + " : 获取锁失败...");
} else {
System.out.println(Thread.currentThread().getName() + " 持有的锁由于已经被被的线程修改锁不用次线程进行释放.");
}
}
}

@Override
public LockResult lock(String lockName) {
return lock(lockName, Long.MAX_VALUE, Long.MAX_VALUE);
}
}

 测试:
redis实现分布式锁_分布式锁


举报

相关推荐

0 条评论