背景
通过springboot整合Redission实现分布式锁
可重入锁
可重入锁,也叫做递归锁,是指在一个线程中可以多次获取同一把锁,比如:一个线程在执行一个带锁的方法,该方法中又调用了另一个需要相同锁的方法,则该线程可以直接执行调用的方法【即可重入】,而无需重新获得锁;对于不同线程则相当于普通的互斥锁。
为什么要用可重入锁,因为即时在单线程的环境下,方法直接互相调用是十分场景的,比如方法A调用方法B,方法B调用方法C,方法C调用方法A,那这个锁如果是
Redission使用可重入锁
互斥锁测试:
@Service
public class RedisServiceImpl implements RedisService {
private static final Logger logger = LoggerFactory.getLogger(RedisServiceImpl.class);
@Autowired
private RedissonClient redissonClient;
@Override
public void testLock() {
logger.info(Thread.currentThread().getName()+":begin");
RLock lock = redissonClient.getLock("testLock");
try {
lock(lock);
} catch (InterruptedException e) {
logger.error("获取锁失败");
} finally {
// lock.unlock();
logger.info("end");
}
}
private void lock(RLock lock) throws InterruptedException {
boolean result = lock.tryLock(5, 30, TimeUnit.SECONDS);
logger.info(Thread.currentThread().getName()+"加锁结果:"+result);
int holdCount = lock.getHoldCount();
String name = lock.getName();
logger.info("当前线程加锁结果:"+name+":"+holdCount);
if(result)
Thread.sleep(30000);
}
}
连续发出两次http请求,输出结果:
2022-03-26 14:52:10.493 INFO 52327 --- [nio-8080-exec-3] c.lin.app.service.impl.RedisServiceImpl : http-nio-8080-exec-3:begin
2022-03-26 14:52:10.494 INFO 52327 --- [nio-8080-exec-3] c.lin.app.service.impl.RedisServiceImpl : http-nio-8080-exec-3加锁结果:true
2022-03-26 14:52:10.495 INFO 52327 --- [nio-8080-exec-3] c.lin.app.service.impl.RedisServiceImpl : 当前线程加锁结果:testLock:1
2022-03-26 14:52:14.187 INFO 52327 --- [nio-8080-exec-5] c.lin.app.service.impl.RedisServiceImpl : http-nio-8080-exec-5:begin
2022-03-26 14:52:19.192 INFO 52327 --- [nio-8080-exec-5] c.lin.app.service.impl.RedisServiceImpl : http-nio-8080-exec-5加锁结果:false
2022-03-26 14:52:19.205 INFO 52327 --- [nio-8080-exec-5] c.lin.app.service.impl.RedisServiceImpl : 当前线程加锁结果:testLock:0
2022-03-26 14:52:19.206 INFO 52327 --- [nio-8080-exec-5] c.lin.app.service.impl.RedisServiceImpl : end
2022-03-26 14:52:40.501 INFO 52327 --- [nio-8080-exec-3] c.lin.app.service.impl.RedisServiceImpl : end
可重入锁测试代码:
@Service
public class RedisServiceImpl implements RedisService {
private static final Logger logger = LoggerFactory.getLogger(RedisServiceImpl.class);
@Autowired
private RedissonClient redissonClient;
@Override
public void testLock() {
logger.info(Thread.currentThread().getName()+":begin");
RLock lock = redissonClient.getLock("testLock");
try {
lock(lock);
((Runnable) () -> {
try {
lock(lock);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).run();
} catch (InterruptedException e) {
logger.error("获取锁失败");
} finally {
logger.info("end");
}
}
private void lock(RLock lock) throws InterruptedException {
boolean result = lock.tryLock(5, 30, TimeUnit.SECONDS);
logger.info(Thread.currentThread().getName()+"加锁结果:"+result);
int holdCount = lock.getHoldCount();
String name = lock.getName();
logger.info("当前线程加锁结果:"+name+":"+holdCount);
if(result)
Thread.sleep(30000);
}
}
输出结果:
2022-03-26 15:07:00.403 INFO 52581 --- [nio-8080-exec-2] c.lin.app.service.impl.RedisServiceImpl : http-nio-8080-exec-2:begin
2022-03-26 15:07:00.415 INFO 52581 --- [nio-8080-exec-2] c.lin.app.service.impl.RedisServiceImpl : http-nio-8080-exec-2加锁结果:true
2022-03-26 15:07:00.416 INFO 52581 --- [nio-8080-exec-2] c.lin.app.service.impl.RedisServiceImpl : 当前线程加锁结果:testLock:1
2022-03-26 15:07:00.437 INFO 52581 --- [nio-8080-exec-2] c.lin.app.service.impl.RedisServiceImpl : http-nio-8080-exec-2加锁结果:true
2022-03-26 15:07:00.438 INFO 52581 --- [nio-8080-exec-2] c.lin.app.service.impl.RedisServiceImpl : 当前线程加锁结果:testLock:2