(此文章实现有误,修正版地址 : https://blog.csdn.net/qq315737546/article/details/79728676)
锁的原理, 就是设置个flag,记录下是否正被使用,可重入锁再判断下是否是自己在使用.
这个flag,必须保证所有资源用的是同一个.
synchronized关键字,lock类等, 可以保证此flag在单个jvm中唯一, 但是有多个jvm(集群,分布式)时候,就没办法保证了.
这时候需要用一个 跨jvm唯一的flag. 也就是常说的分布式锁了.
分布式锁的实现也有很多种. 基于redis,zookeeper等等, 也可以基于数据库.
基于redis的,也有setnx,incr等操作的.
本着简单,实用的原则, 写了一个简单的类,主要支持以下功能:
1.所有加锁操作都需要有时间限制,不能无限锁定
2.提供获取失败重试机制
3.释放锁时,保证释放的锁是自己获取到的
下面是代码,用到了jedis的jar, redis的连接是和spring整合配置的.这里就不列了. 所以不能直接运行
重点是LockUtil类.(锁存在,检查锁的剩余时间,然后重试,这里没有扣减此过程消耗的时间.所以极端情况会出现超出tryLock的timeOut设置而获取到锁)
import java.util.Objects;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.zhidian.common.util.SpringContextUtil;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisException;
/**
* 基于redis setnx的 分布式锁 实, 前提是所有的锁都要有锁定时间.
* 获取锁的时候,需要指定value,在unlock的时候,会根据value判断是否remove
*
* @author: qq315737546
*/
public class LockUtil {
private static Log logger = LogFactory.getLog(LockUtil.class);
private static final String LOCK_PREFIX = "LOCK";
private static final Integer DEFAULT_LOCK_TIME = 20;// 默认锁定时间秒
private static final Long DEFAULT_SLEEP_TIME = 100L;// 默认sleep时间,100毫秒
/**
* 单台服务器可直接用系统时间,多台服务器可用redis.time()
*
* @return
* @Author: qq315737