关于CacheInterceptor源码中使用ReentrantLock锁问题

今天在阅读jfinal中CacheInterceptor这个类的源码的时候遇到点疑惑,请看下面代码截图

WM}KHG8AI2ZL2QF@UU5Z9S4.png

我有点疑惑当从缓存中获取数据为空的时候,为什么要使用ReentrantLock同步锁呢,CacheKit.get方法中取数据的时候不是已经加上了synchronized同步锁吗?希望热心网友帮忙指点下

评论区

杜福忠

2020-06-15 10:05

CacheKit.get时候加的synchronized,只保障缓存取值的时空。
ReentrantLock保障客户端请求和inv.invoke()等代码处理的时空。
两回事啊

穿越123

2020-06-15 10:37

@杜福忠 有道理,不过我看Jboot源码中的缓存拦截器好像没使用到同步锁

JFinal

2020-06-15 20:31

@穿越123 这个锁,只会在 cacheData 为 null 时被使用,所以对性能不会有任何影响

它的作用是,在 cache 中的数据还未被填充时,如果大量并发请求涌来,会产生雪崩,也就是说,大量请求同时看到这个 cacheData 为 null, 进而同时去查数据库

如果是较耗时的查询,这个时候数据库一般会就崩掉

而这个锁就保障了,cacheData 为 null 时,只有一个线程允许许去查询数据库,其它的等待,而等待的线程被唤醒时,cache 中的数据已填充好,就不必去查询数据库了


要写好高并发多线程代码对基本功要求比较高。 jfinal 源码中有大量精心编写的代码,是提升技术的绝佳资源

但可惜的是,认真读源码的同学并不多

doubuxingle

2020-06-18 14:47

@JFinal
波总,请教下。
try 里面是不是不用再cacheKit.get了哦。 直接if(cacheData==null) 是不是也可以

穿越123

2020-06-19 16:10

@JFinal 嗯,一直认为jfinal源码设计的很通俗易懂,从中可以学会底层的知识,感谢波总的指导,听君一席话胜读十年书

JFinal

2020-06-20 17:31

@穿越123 将事情搞复杂是很容易的,反之是很难的,jfinal 擅长将复杂问题简化

JFinal

2020-06-20 17:33

@doubuxingle 当某个线程被 lock.lock() 锁住的时候,它持有的 cacheData 是 null,当该线程被重新唤醒时必须再通过 CacheKit.get(...) 获取数据,否则 cacheData 仍是 null,那这段代码就毫无意义了

热门反馈

扫码入社