AQS – ReentrantReadWriteLock应用与源码解读

读写锁概要

读锁是共享锁,写锁是排他锁
公平锁的策略是将锁分配给等待时间最长的锁,因此公平读锁、写锁是不可重入锁?
写锁是排他锁,同一时间段只允许一个线程获取写锁,因此是不可重入锁?
非公平读锁允许多个读线程同时获取读锁,因此是可重入锁?
读锁不能升级为写锁,写锁可以降级为读锁
Condition只能和写锁搭配使用

共享锁和排他锁的相容性

共享锁 排他锁
共享锁 ×
排他锁 × ×

官方案例讲解

class CachedData {
    Object data;
    volatile boolean cacheValid;
    final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

    void processCachedData() {
        rwl.readLock().lock();
        if (!cacheValid) {
            rwl.readLock().unlock();
            // 读锁
            rwl.writeLock().lock();
            try {
                if (!cacheValid) {
                    data = ...
                    cacheValid = true;
                }
                // 写锁可降级为读锁
                rwl.readLock().lock();
            } finally {
                // 释放写锁,但不释放降级后的读锁
                rwl.writeLock().unlock();
            }
        }

        try {
            use(data);
        } finally {
            rwl.readLock().unlock();
        }
    }
}
class RWDictionary {
    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 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 – Java™ Platform Standard Ed. 8

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

©2018-2024 Howell版权所有 备案号:冀ICP备19000576号