1、了解分布式锁的特性
- 1、锁的互斥性
- 也就是说,在任意时刻,只能有一个客户端能获取到锁,不能同时有两个或多个客户端获取到锁 。
- 简单来说,就比如上厕所,一个厕所只有一个坑位,只能一个人上,不能同时两个人或多个人上 。
- 2、锁的同一性
- 也就是说,锁只能被持有该锁的客户端进行删除(释放锁),不能由其他客户端删除 。
- 简单俩说,就是谁加的锁,就只能谁来解锁 。也就是解铃还须系铃人 。
- 3、锁的可重入性
- 也就是说,持有某个锁的客户端,可以继续对该锁进行加锁,实现锁的续租 。
- 简单来说,就是你上厕所的按时间收费的,时间快到了会按照时间给你续租,而会给你价钱 。
- 而redisson则会增大的你的续租次数,也就是可重入次数 。但绝不收费,因为Redis是开源的嘛 。
- 4、锁的容错性
- 锁超过了最大续租时间后,会自动释放锁,其他客户端会继续获得该锁,从而防止死锁的发生 。
- 简单来说,比如你上个厕所上了五小时,厕管员觉得不对劲,就来测试,发现你悄悄逃票了,此时测试会自动变成解锁状态,其他人就可以去上了,只是厕管员血亏5块大洋 。
public TestEntity getById2(Long id){RLock lock = redissonClient.getLock("demo2_lock");lock.lock(20, TimeUnit.SECONDS);index++;log.info("current index is : {}", index);TestEntity testEntity = new TestEntity(new Random().nextLong(), UUID.randomUUID().toString(), new Random().nextInt(20) + 10);log.info("模拟查询数据库:{}", testEntity);lock.unlock();return testEntity;}
2.1、关注Redisson.getLock()方法@Overridepublic RLock getLock(String name) {return new RedissonLock(commandExecutor, name);}
其实就是创建一个RedissonLock对象,所以加锁的逻辑就在RedissonLock.lock()中,解锁的逻辑就在RedissonLock.unlock() 。2.2、关注RedissonLock.lock()方法
// RedissonLock.lock()的方法体public void lock(long leaseTime, TimeUnit unit) {try {// 调用了lock的重载方法lock(leaseTime, unit, false);} catch (InterruptedException e) {throw new IllegalStateException();}}
关注lock的重载方法// leaseTime表示最大续时间,unit表示续约时间单位,interruptibly表示是否可以中断private void lock(long leaseTime, TimeUnit unit, boolean interruptibly) throws InterruptedException {// 获取当前线程的线程IDlong threadId = Thread.currentThread().getId();// 尝试获取锁,结果为null表示此时没有客户端占用锁,绝不矫情,直接拿到锁就返回 。// 结果ttl>0的话,表示此时已经有了其他不识好歹的客户端暂用了锁,那么就只能绝望的等待了Long ttl = tryAcquire(-1, leaseTime, unit, threadId);// lock acquiredif (ttl == null) {return;}// 等待时订阅一个渠道,如果锁被其他客户端释放了,会通过发布订阅模式在publish上发一个消息,表示锁已经释放了CompletableFuture<RedissonLockEntry> future = subscribe(threadId);pubSub.timeout(future);RedissonLockEntry entry;if (interruptibly) {entry = commandExecutor.getInterrupted(future);} else {entry = commandExecutor.get(future);}try {// 我干等这不是办法,我还是要不断去尝试看能不能获取锁while (true) {ttl = tryAcquire(-1, leaseTime, unit, threadId);// 如果TTL为空了,表示获取到了锁,那还等什么,长驱直入就是 。if (ttl == null) {// 结束循环等待break;}// 如果ttl还是大于0的,表示其他客户端真的是过于不识好歹,还不肯释放锁 。但好歹还是说了它还要持有错多久 。if (ttl >= 0) {try {// 既然如此,那么我就等待你的时间到达吧,除非我突然有啥事被中断了,否则我就等到你过期entry.getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);} catch (InterruptedException e) {// 如果传入了中断标识,直接抛出异常,中断了,干别的事情去if (interruptibly) {throw e;}// 否则还是老老实实的继续等待时间到来entry.getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);}}// 锁过期时间小于0,表示那个杀千刀的客户端居然没有设置超时时间,它包场了,这可咋整 。else {// 如果不被中断,那么我也只有无期限的等待下去了,我不希望这个期限是一万年if (interruptibly) {entry.getLatch().acquire();} else {entry.getLatch().acquireUninterruptibly();}}}} finally {// 最后,不管如何,我无论如何都要去取消订阅这个publish的消息,因为这会浪费我的精力,这已经是我最后的坚持了 。// 其实是释放资源unsubscribe(entry, threadId);}//get(lockAsync(leaseTime, unit));}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 一文吃透JVM分代回收机制
- Springboot+Redisson封装分布式锁Starter
- AMD中国特供新卡RX 6750 GRE:原来是RX 6700矿卡解锁
- 解析SPI机制:实现灵活插件式架构
- 苹果激活锁是啥意思 苹果激活锁是什么意思
- 设置苹果面部解锁步骤方法 苹果咋设置面部解锁
- 起猛了!赵丽颖谢娜一起看张杰演唱会,还现场解锁了新技能蹦迪
- 《四方馆》首发剧照,檀健次解锁新造型,女主表现超预期!
- 七夕,翡你不可,用翡翠锁住心上人
- 立竿见影!教师“退出机制”才刚落地,教师招聘就“遇冷”了?