Java 并发编程实战
王宝令
资深架构师
72485 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 51 讲
学习攻略 (1讲)
Java 并发编程实战
15
15
1.0x
00:00/00:00
登录|注册

17 | ReadWriteLock:如何快速实现一个完备的缓存?

使用写锁
使用读锁
支持
不支持
按需加载
一次性加载
put()方法
get()方法
使用读写锁保证线程安全
写操作互斥
只允许一个线程写共享变量
允许多个线程同时读共享变量
数据同步问题的解决方案
读写锁的特性
锁的降级
锁的升级
缓存数据的初始化问题
Cache<K, V>类
读写锁与互斥锁的区别
读写锁基本原则
缓存优化性能
课后思考
总结
读写锁的升级与降级
按需加载示意图
实现缓存
读多写少场景
读写锁
参考文章

该思维导图由 AI 生成,仅供参考

前面我们介绍了管程和信号量这两个同步原语在 Java 语言中的实现,理论上用这两个同步原语中任何一个都可以解决所有的并发问题。那 Java SDK 并发包里为什么还有很多其他的工具类呢?原因很简单:分场景优化性能,提升易用性
今天我们就介绍一种非常普遍的并发场景:读多写少场景。实际工作中,为了优化性能,我们经常会使用缓存,例如缓存元数据、缓存基础数据等,这就是一种典型的读多写少应用场景。缓存之所以能提升性能,一个重要的条件就是缓存的数据一定是读多写少的,例如元数据和基础数据基本上不会发生变化(写少),但是使用它们的地方却很多(读多)。
针对读多写少这种并发场景,Java SDK 并发包提供了读写锁——ReadWriteLock,非常容易使用,并且性能很好。
那什么是读写锁呢?
读写锁,并不是 Java 语言特有的,而是一个广为使用的通用技术,所有的读写锁都遵守以下三条基本原则:
允许多个线程同时读共享变量;
只允许一个线程写共享变量;
如果一个写线程正在执行写操作,此时禁止读线程读共享变量。
读写锁与互斥锁的一个重要区别就是读写锁允许多个线程同时读共享变量而互斥锁是不允许的,这是读写锁在读多写少场景下性能优于互斥锁的关键。但读写锁的写操作是互斥的当一个线程在写共享变量的时候,是不允许其他线程执行写操作和读操作。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文详细介绍了如何使用Java SDK并发包中的ReadWriteLock来实现一个高效的缓存工具类。通过解释读多写少的并发场景下为什么需要使用缓存以及读写锁的基本原则,文章引出了使用缓存的必要性。接着,通过示例代码演示了如何使用ReadWriteLock来实现一个通用的缓存工具类,包括读缓存和写缓存的实现。此外,文章还介绍了缓存数据的初始化问题,包括一次性加载和按需加载的方式,并提供了相应的示意图。另外,文章还详细讲解了在高并发场景下如何实现缓存的按需加载,以及读写锁的升级与降级的问题。总的来说,本文通过实际示例和详细讲解,帮助读者快速了解了如何利用ReadWriteLock来实现一个高效的缓存工具类,以及在实际应用中需要注意的细节和技巧。文章还提到了解决数据同步问题的超时机制,以及在源头数据发生变化时如何快速反馈给缓存的方案。最后,文章提出了一个课后思考问题,引发读者思考如何验证读锁升级写锁的方案是否导致系统停止响应的问题。整体而言,本文内容丰富,涵盖了缓存工具类的实现细节和相关技术特点,对读者具有很高的参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 并发编程实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(120)

  • 最新
  • 精选
  • 西西弗与卡夫卡
    考虑到是线上应用,可采用以下方法 1. 源代码分析。查找ReentrantReadWriteLock在项目中的引用,看下写锁是否在读锁释放前尝试获取 2. 如果线上是Web应用,应用服务器比如说是Tomcat,并且开启了JMX,则可以通过JConsole等工具远程查看下线上死锁的具体情况

    作者回复: 👍

    2019-04-06
    5
    73
  • ycfHH
    问题1:获取写锁的前提是读锁和写锁均未被占用? 问题2:获取读锁的前提是没有其他线程占用写锁? 基于以上两点所以只支持锁降级而不允许锁升级。 问题3 高并发下,申请写锁时是不是中断其他线程申请读锁,然后等待已有读锁全部释放再获取写锁?因为如果没有禁止读锁的申请的话在读多写少的情况下写锁可能一直获取不到。 这块不太懂,希望老师能指点一下。

    作者回复: 获取写锁的前提是读锁和写锁均未被占用 获取读锁的前提是没有其他线程占用写锁 申请写锁时不中断其他线程申请读锁 公平锁如果过有写申请,能禁止读锁

    2019-05-07
    5
    55
  • 缪文
    老师,感觉这里的读写锁,性能还有可以提升的地方,因为这里可能很多业务都会使用这个缓存懒加载,实际生产环境,写缓存操作可能会比较多,那么不同的缓存key,实际上是没有并发冲突的,所以这里的读写锁可以按key前缀拆分,即使是同一个key,也可以类似ConcurrentHash 一样分段来减少并发冲突

    作者回复: 可以这样

    2019-04-07
    7
    55
  • sibyl
    老师好,回答一下有些同学关于读锁有什么用的疑问,您看看对不对,如果对,给个置顶鼓励一下,谢谢老铁啦,啊哈哈 1、有些同学认为读锁没有用,他们的理由是:读操作又不会修改数据,想读就读呗,无论读的是就值还是新值,反正能读到。 2、也有同学认为读锁是为了防止多线程读到的数据不一致。 我认为不是这个原因,只需要问两个问题就知道了,首先问不一致的是什么?然后反问不一致会导致什么问题呢? 有些同学认为不一致就是有些线程读的是旧值,有些读的是新值,所以不一致。但是反问导致什么问题,就不是很好回答了,可能回答说为了保险吧,哈哈哈。 实际上即使加读锁,还是会存在有的线程读旧值,有的线程读新值,甚至非公平锁情况下,先开始的线程反而读到新值,而后开始的线程反而读到旧值,所以读锁并不是为了保证多线程读到的值是一样的。 3、那么读锁的作用是什么呢? 任何锁表面上是互斥,但本质是都是为了避免原子性问题(如果程序没有原子性问题,那只用volatile来避免可见性和有序性问题就可以了,效率更高),读锁自然也是为了避免原子性问题,比如一个long型参数的写操作并不是原子性的,如果允许同时读和写,那读到的数很可能是就是写操作的中间状态,比如刚写完前32位的中间状态。long型数都如此,而实际上一般读的都是复杂的对象,那中间状态的情况就更多了。 所以读锁是防止读到写操作的中间状态的值。

    作者回复: 尤其是涉及多个共享变量的时候,这个作用尤其明显,如果只是一个int,就不那么明显了。

    2020-07-10
    7
    35
  • crazypokerk
    老师,可不可以这样理解,ReadWirteLock不支持锁的升级,指的是:在不释放读锁的前提下,无法继续获取写锁,但是如果在释放了读锁之后,是可以升级为写锁的。锁的降级就是:在不释放写锁的前提下,获取读锁是可以的。请老师指正,感谢。

    作者回复: 可以这样理解,不过释放了读锁,也就谈不上升级了

    2019-04-06
    5
    29
  • WhoAmI
    一般都说线程池有界队列使用ArrayBlockingQueue,无界队列使用LinkedBlockingQueue,我很奇怪,有界无界不是取决于创建的时候传不传capacity参数么,我现在想创建线程池的时候,new LinkedBlockingQueue(2000)这样定义有界队列,请问可以吗?

    作者回复: 可以,ArrayBlockingQueue有界是因为必须传capacity参数,LinkedBlockingQueue传capacity参数就是有界,不传就是无界

    2019-04-06
    4
    20
  • WL
    老师我们现在的项目全都是集群部署, 感觉在这种情况下是不是单机的Lock,和Synchronized都用不上, 只能采用分布式锁的方案? 那么这种情况下, 如何提高每个实例的并发效率?

    作者回复: 分布式有分布式的锁,单机的效率就是靠多线程了

    2019-04-09
    17
  • 探索无止境
    老师你好,我们在项目开发中,如果要实现缓存,会直接采用Redis,感觉更合适,所以不太清楚,实际中ReadWriteLock可以解决哪些问题?

    作者回复: 本地缓存更快

    2019-08-26
    5
    11
  • 文灏
    王老师你好,有个问题想请教一下。既然允许多个线程同时读,那么这个时候的读锁意义在哪里?

    作者回复: 不用关心可见性,原子性,读到的都是对的

    2019-05-22
    5
    10
  • 随风而逝
    缓存一致性问题,我们都是双删缓存。老师,读写锁的降级和单独使用有什么区别?或者说有什么优势?

    作者回复: 降级稍微快一点,而且一定能成功。

    2019-04-22
    2
    9
收起评论
显示
设置
留言
99+
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部