1.分布式锁概念
关于锁,其实我们或多或少都有接触过一些,比如synchronized、 Lock这些,这类锁的目的很简单,在多线程环
境下,对共享资源的访问造成的线程安全问题,通过锁的机制来实现资源访问互斥。那么什么是分布式锁呢?或者
为什么我们需要通过Redis来构建分布式锁,其实最根本原因就是Score(范围),因为在分布式架构中,所有的应
用都是进程隔离的,在多进程访问共享资源的时候我们需要满足互斥性,就需要设定一个所有进程都能看得到的范
围,而这个范围就是Redis本身。所以我们才需要把锁构建到Redis中。
Redis里面提供了一些比较具有能够实现锁特性的命令,比如SETEX(在键不存在的情况下为键设置值),那么我们可
以基于这个命令来去实现一些简单的锁的操作
2.分布式锁需要具备的特性
- 能够获取锁和释放锁
- 不会产生死锁(具有超时释放机制)
- 释放者必须是加锁者
3.代码实现
获取jedis连接
public class GpJedisConnectionUtil {
private static JedisPool jedisPool = null;
static{
JedisPoolConfig jpc = new JedisPoolConfig();
jpc.setMaxTotal(100);
jedisPool = new JedisPool(jpc,"114.115.204.56",6379,5000,"123wan12345");
}
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
分布式锁实现
public class GpDistributeLock {
public static boolean acquireLock(String lockName , long acquireTimeout , long lockTimeout ){
String realLockName = "lock:"+lockName;
String theadId = String.valueOf(Thread.currentThread().getId());
Jedis jedis = null;
int lockTimeoutMin = (int) (lockTimeout / 1000);
long acquireEndTime = System.currentTimeMillis() + acquireTimeout;
try{
jedis = GpJedisConnectionUtil.getJedis();
while(System.currentTimeMillis() < acquireEndTime){
if(jedis.setnx(realLockName,theadId) == 1 || theadId.equals(jedis.get(realLockName))){ //加锁成功
System.out.println("线程"+theadId+"获取锁成功");
jedis.expire(realLockName , lockTimeoutMin);
return true;
}
if(jedis.ttl(realLockName) == -1){ //死锁
jedis.expire(realLockName , lockTimeoutMin);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}finally {
jedis.close();
}
return false;
}
public static boolean releaseLock(String lockName){
String realLockName = "lock:"+lockName;
long theadId = Thread.currentThread().getId();
Jedis jedis = null;
boolean isRelease = false;
try{
while(true){
jedis = GpJedisConnectionUtil.getJedis();
//jedis事务操作 监控realLockName 如果其中值发生变化tx.exec事务不会提交(注jedis中的事务不具备原子性,其中一个事务有错误,另外的仍然执行)
jedis.watch(realLockName);
if(String.valueOf(theadId).equals(jedis.get(realLockName))){
Transaction tx = jedis.multi();
tx.del(realLockName);
if(tx.exec().isEmpty())
continue;
System.out.println("线程"+theadId+"释放锁成功");
isRelease = true;
return isRelease;
}
jedis.unwatch(); //q取消监控
break;
}
}finally {
jedis.close();
}
re
测试
public class Test implements Runnable{
@Override
public void run() {
while(true){
if(GpDistributeLock.acquireLock("updateGoods",2000,5000)){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
GpDistributeLock.releaseLock("updateGoods");
break;
}
}
}
public static void main(String[] args) {
Test runable = new Test();
for (int i =0;i<10; i++){
new Thread(runable).start();
}
}
}
结果
线程17获取锁成功
线程17释放锁成功
线程15获取锁成功
线程15释放锁成功
线程14获取锁成功
线程14释放锁成功
线程11获取锁成功
线程11释放锁成功
线程19获取锁成功
线程19释放锁成功
线程18获取锁成功
线程18释放锁成功
线程16获取锁成功
线程16释放锁成功
线程13获取锁成功
线程13释放锁成功
线程20获取锁成功
线程20释放锁成功
线程12获取锁成功
线程12释放锁成功