【漫画】互斥锁ReentrantLock不好用?试试读写锁ReadWriteLock (2)

原创声明:本文来源于微信公众号【胖滚猪学编程】,持续更新JAVA\大数据干货,用漫画形式让编程so easy and interesting。转载请注明出处。

ReentrantReadWriteLock的特色功能

在,我们介绍了ReentrantLock相比synchronized的几大特色功能,例如公平锁、非阻塞获取锁、超时、中断。那么ReentrantReadWriteLock是否也有呢?

简单。。看看源码不就清楚了。以下源码都是在ReentrantReadWriteLock.java中撩出来的~ 剩下的我就不用多说了吧!如果不清楚这些方法可以回头看看

public ReentrantReadWriteLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); readerLock = new ReadLock(this); writerLock = new WriteLock(this); } public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } 读写锁的升级与降级

还想跟你聊聊锁的升级和降级。也许你是第一次听到,锁还有升级降级的功能。但其实不难理解,比如在读写锁中,写锁变为读锁是完全可行的方案,不会有任何问题,这里写锁变读锁就叫做锁的降级

那么可以升级吗?熟话说降级容易,你只要天天不来上班就行了,升级可难哦。锁中也是,只是在锁中更加苛刻,完全不允许升级,即读锁无法升级为写锁必须先释放读锁,才可以获取写锁。为什么不允许升级?试想有1000个读线程同时执行,同时升级为写锁,会发生什么?获取写锁的前提是读锁和写锁均未被占用,因此可能导致阻塞较长的时间,也可能发生死锁。

先写个代码验证一下吧,在(2)处我们实现了降级,程序是完全ok的,在(1)处如果你注释掉 r.unlock(),试图升级为读锁,你会发现程序会跑不下去的,据此可以验证我们所说的:读写锁可以降级、无法升级。

void processCachedData() { // 获取读锁 r.lock(); if (!cacheValid) { // 释放读锁 因为不允许读锁的升级 可以注释掉该行代码 整个程序会阻塞 r.unlock(); //(1) // 获取写锁 w.lock(); try { // 再次检查状态 if (!cacheValid) { data = "胖滚猪学编程"; cacheValid = true; } // 释放写锁前 降级为读锁 降级是可以的 r.lock(); //(2) } finally { // 释放写锁 w.unlock(); } } // 此处仍然持有读锁 try { System.out.println(data); } finally { r.unlock(); } } 总结

读写锁适用于读多写少的情况。可以优化性能,提升易用性。缓存就是个很好的例子。

读写锁最大的特征是允许多个线程同时读共享变量。但是只允许一个线程写共享变量,且如果一个写线程正在执行写操作,此时禁止读线程读共享变量。

ReentrantReadWriteLock读写锁类似于 ReentrantLock,支持公平模式和非公平模式、支持非阻塞获取锁、超时、中断等特性。但是有一点需要注意,那就是只有写锁支持条件变量,读锁是不支持条件变量的,读锁调用 newCondition() 会抛出 UnsupportedOperationException 异常。

所以!我们必须了解各种锁的用途,才能在生产上选择最合适高效的方式。

原创声明:本文来源于微信公众号【胖滚猪学编程】,持续更新JAVA\大数据干货,用漫画形式让编程so easy and interesting。转载请注明出处。

本文转载自公众号【胖滚猪学编程】 用漫画让编程so easy and interesting!欢迎关注!形象来源于微信表情包【胖滚家族】喜欢可以下载哦~

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zggyjx.html