三、线程加锁成功后继续申请加锁
?这个场景主要发生在加锁代码内部调用栈过深,比如说加锁成功执行方法 a,在方法 a 内又重复申请了同一把锁 , 导致线程把自己锁住了,这个业界的主流叫法是叫锁的可重入性 。解决方式有两种,一是修改方法内的加锁逻辑,不要加同一把锁 , 修改方法 a 内的加锁 key 名称 。二是针对加锁逻辑做修改,实现可重入性 。
?
这里简单介绍如何实现可重入性,给每个线程设置请求ID , 加锁成功将请求ID设置为加锁 key 的对应 value,针对同一个线程的重复加锁,判断当前线程已存在请求ID的情况下,请求ID直接与加锁 key 的对应 value 相比较,相同则直接返回加锁成功 。
四、 代码实践4.1 加锁自动续期实践设置锁过期时间为10秒 , 然后该任务执行15秒,代码如下:
?ps: 以下代码都可以在 https://github.com/wayn111/newbee-mall-pro 项目test目录下RedisLockTest类中找到
?
@Slf4j@SpringBootTest@RunWith(SpringRunner.class)public class RedisLockTest { @Autowired private RedisLock redisLock; @Test @Test public void redisLockNeNewTest() { String key = "test"; try { log.info("---申请加锁"); if (redisLock.lock(key, 10)) { // 模拟任务执行15秒 log.info("---加锁成功"); Thread.sleep(15000); log.info("---执行完毕"); } } catch (Exception e) { log.error(e.getMessage(), e); } finally { redisLock.unLock(key); } }}执行如下:
文章插图
可以看出就算任务执行超过过期时间也能通过自动续期让代码正常执行 。
4.2 多线程下其他线程无法共同申请到同一把锁实践启动两个线程,线程 A 先加锁 , 线程 B 后枷锁
@Testpublic void redisLockReleaseSelfTest() throws IOException { new Thread(() -> { String key = "test"; try { log.info("---申请加锁"); if (redisLock.lock(key, 10)) { // 模拟任务执行15秒 log.info("---加锁成功"); Thread.sleep(15000); log.info("---执行完毕"); } else { log.info("---加锁失败"); } } catch (Exception e) { log.error(e.getMessage(), e); } finally { redisLock.unLock(key); } }, "thread-A").start(); new Thread(() -> { String key = "test"; try { Thread.sleep(100L); log.info("---申请加锁"); if (redisLock.lock(key, 10)) { // 模拟任务执行15秒 log.info("---加锁成功"); Thread.sleep(15000); log.info("---执行完毕"); } else { log.info("---加锁失败"); } } catch (Exception e) { log.error(e.getMessage(), e); } finally { redisLock.unLock(key); } }, "thread-B").start(); System.in.read();}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Redis 也支持全文搜索?这也太强了
- 聊聊分布式数据库TDSQL的技术架构
- pr怎么锁定图层,ps要怎么才可以锁定图层
- 华为手机触屏解锁怎么设置,华为解锁直接进入桌面怎么设置
- 刘德华11岁女儿时隔5年露面!眉头深锁送别爷爷,长得与妈妈极像
- 解锁 C++ 并发编程的钥匙:探索 Atomic 变量
- MySQL:逃不掉的锁事,间隙锁
- 宋祖英终于换对新发型,56岁嫩回36岁,锁骨短发配粉衣少女感十足
- 栖桐国际:面霜可以锁住皮肤表面,形成一个保护层,防止水分流失
- TVB女星自曝被赶出家门!密码锁被改衣服被扔掉,新婚4个月
