2023-08-15  阅读(7)
原文作者:Ressmix 原文地址:https://www.tpvlog.com/article/18

一、ReentrantReadWriteLock类简介

ReentrantReadWriteLock类,顾名思义,是一种读写锁,它是ReadWriteLock接口的直接实现,该类在内部实现了具体 独占锁 特点的写锁,以及具有 共享锁 特点的读锁,和ReentrantLock一样,ReentrantReadWriteLock类也是通过定义内部类实现AQS框架的API来实现独占/共享的功能。

ReentrantReadWriteLock类具有如下特点:

1.1 支持公平/非公平策略

与ReadWriteLock类一样,ReentrantReadWriteLock对象在构造时,可以传入参数指定是公平锁还是非公平锁。

202308152155571091.png

1.2 支持锁重入

  • 同一读线程在获取了读锁后还可以获取读锁;
  • 同一写线程在获取了写锁之后既可以再次获取写锁又可以获取读锁;

1.3 支持锁降级

所谓锁降级,就是:先获取写锁,然后获取读锁,最后释放写锁,这样写锁就降级成了读锁。但是,读锁不能升级到写锁。简言之,就是:

写锁可以降级成读锁,读锁不能升级成写锁。

1.4 Condition条件支持

ReentrantReadWriteLock的内部读锁类、写锁类实现了Lock接口,所以可以通过newCondition()方法获取Condition对象。但是这里要注意,读锁是没法获取Condition对象的,读锁调用newCondition()方法会直接抛出UnsupportedOperationException

我们知道,condition的作用其实是对Object类的wait()notify()的增强,是为了让线程在指定对象上等待,是一种线程之间进行协调的工具。
当线程调用condition对象的await方法时,必须拿到和这个condition对象关联的锁。由于线程对读锁的访问是不受限制的(在写锁未被占用的情况下),那么即使拿到了和读锁关联的condition对象也是没有意义的,因为读线程之前不需要进行协调。

1.5 使用示例

以下是Oracle官方给出的一个例子:
使用ReentrantReadWriteLock控制对TreeMap的访问(利用读锁控制读操作的访问,利用写锁控制修改操作的访问),将TreeMap包装成一个线程安全的集合,并且利用了读写锁的特性来提高并发访问。

    public class RWTreeMap {
        private final Map<String, Data> m = new TreeMap<String, Data>();
        private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
        private final Lock r = rwl.readLock();
        private final Lock w = rwl.writeLock();
    
        public Data get(String key) {
            r.lock();
            try {
                return m.get(key);
            } finally {
                r.unlock();
            }
        }
    
        public String[] allKeys() {
            r.lock();
            try {
                return (String[]) m.keySet().toArray();
            } finally {
                r.unlock();
            }
        }
    
        public Data put(String key, Data value) {
            w.lock();
            try {
                return m.put(key, value);
            } finally {
                w.unlock();
            }
        }
    
        public void clear() {
            w.lock();
            try {
                m.clear();
            } finally {
                w.unlock();
            }
        }
    }

二、ReentrantReadWriteLock类/方法声明

2.1 类声明

202308152155592072.png

内部嵌套类声明:
ReentrantReadWriteLock类有两个内部嵌套类ReadLockWriteLock,这两个内部类的实例会在ReentrantReadWriteLock类的构造器中创建,并通过ReentrantReadWriteLock类的readLock()writeLock()方法访问。

ReadLock:

202308152156003343.png

WriteLock:

202308152156012434.png

2.2 方法声明

ReentrantReadWriteLock类的核心方法其实就两个:readLock()writeLock(),其它都是一些用来监控系统状态的方法,返回的都是某一时刻点的近似值。

202308152156019895.png


Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。

它的内容包括:

  • 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
  • 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
  • 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
  • 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
  • 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
  • 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
  • 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
  • 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw

目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:

想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询

同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。

阅读全文