1.可重入锁介绍
什么是可重入锁,举个例子
现在我有锁对象lock,在调用A方法内,有用lock锁住
锁住后在A方法内有对B方法的调用,B方法内又有用lock锁住,
如果不是可重入锁,那么调用B方法时就死锁了,因为A方法内lock锁还不会释放,
如果是可重入锁,那么可以直接运行B方法,看到这你应该明白了,同一线程内,一旦获取到了某个锁,那么
线程后续执行还需要此锁,那么可以直接使用
想要详细了解参考:,然后自己去看相关源码
除了synchronize和ReentrantLock及子类,其他都是不可重入。当然借助AQS可自己实现重入锁
2.lock锁测试
IndexController内添加代码如下
@RequestMapping({"/hello"})
@ResponseBody
public String hello(){
//获取一把锁,只要名称一样就是同一把锁
RLock lock = redissonClient.getLock("my-lock");
//加锁 没加上锁的线程阻塞式等待,不用我们之前那样写的自旋
lock.lock();
//模拟业务执行
System.out.println("加锁成功,业务执行中,执行线程为:"+Thread.currentThread().getId());
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//释放锁
System.out.println("释放锁,执行线程为:"+Thread.currentThread().getId());
lock.unlock();
}
return "hello";
}
浏览器同时开俩窗口访问此方法
浏览器显示如下,可以看到一个线程获取锁,执行业务然后释放锁,然后再是另一个线程做同样的操作,没获取锁的线程就阻塞式等待直到锁被释放
以上看到了锁的基本功能,至于我们上一节说的前面,突然宕机或者停电锁没释放,又或者获取锁,解锁原子性问题等等,
Reddison是否有解决呢,简单测试下
现在测试的是一个线程一运行时,加锁之后释放锁之前宕机的问题,若宕机后没有释放锁,那么自然会死锁了
拷贝应用配置,更改端口后启动
启动两服务后访问
此时在10201端口中服务中的锁被获取后停止服务
看到10200服务中的锁依然能被获取,业务照常执行然后释放锁了
说明在宕机后锁被释放了,猜测应该是有一个默认过期时间的,所以在服务停止后锁会被释放,不止这一点,相信
获取锁与解锁的原子性等操作也有lock底层也有实现,业务如果允许时间长也不用担心业务没运行完锁就自动释放,在业务运行期间也会有每隔十秒自动续期的,
下一节带你看看底层代码如何实现的