Java并发 -- ReadWriteLock

栏目: Java · 发布时间: 5年前

内容简介:ReadWriteLock不支持锁升级,readLock还没有释放,无法获取writeLock,导致
  1. 理论上,利用 管程信号量 可以解决所有并发问题,但JUC提供了很多 工具 类, 细分场景优化性能,提升易用性
  2. 针对 读多写少 的并发场景,JUC提供了 读写锁 ,即ReadWriteLock

读写锁

  1. 读写锁是一种广泛使用的 通用技术 ,并非 Java 所特有
  2. 所有读写锁都遵守3条基本原则
    • 允许 多个线程同时读 共享变量 – 与互斥锁的重要区别
    • 只允许 一个线程写 共享变量
    • 如果一个写线程正常执行写操作,此时禁止读线程读取共享变量

缓存

public class Cache<K, V> {
    private final Map<K, V> map = new HashMap<>();
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    // 读锁
    private final Lock readLock = readWriteLock.readLock();
    // 写锁
    private final Lock writeLock = readWriteLock.writeLock();

    // 读缓存 -- 懒加载
    public V get(K key) {
        V v = null;
        // 读缓存
        readLock.lock(); // 1
        try {
            v = map.get(key); // 2
        } finally {
            readLock.unlock(); // 3
        }
        // 缓存中存在,直接返回
        if (v != null) { // 4
            return v;
        }
        // 缓存中不存在,查询数据库
        writeLock.lock(); // 5
        try {
            // 再次验证,其他线程可能已经查询过数据库了
            // 避免在高并发场景下重复查询数据库的问题
            v = map.get(key); // 6
            if (v == null) { // 7
                // 查询数据库
                v = loadFromDb(key);
                map.put(key, v);
            }
        } finally {
            writeLock.unlock();
        }
        return v;
    }

    private V loadFromDb(K key) {
        return null;
    }

    // 写缓存
    public V put(K key, V value) {
        writeLock.lock();
        try {
            return map.put(key, value);
        } finally {
            writeLock.unlock();
        }
    }
}

锁升级

ReadWriteLock不支持锁升级,readLock还没有释放,无法获取writeLock,导致 线程阻塞

readLock.lock();
try {
    V v = map.get(key);
    if (v == null) {
        writeLock.lock();
        try {
            map.put(key, loadFromDb(key));
        } finally {
            writeLock.unlock();
        }
    }
} finally {
    readLock.unlock();
}

锁降级

readLock.lock();
if (!cacheValid) {
    // 因为不允许读锁升级,先释放读锁
    readLock.unlock();
    writeLock.lock();
    try {
        if (!cacheValid) {
            cacheValid = true;
        }
        // 释放写锁前,降级为读锁,这是允许的
        readLock.lock(); // 1
    } finally {
        writeLock.unlock();
    }
}

// 此时仍然持有读锁
try {
    // 使用数据
} finally {
    readLock.unlock();
}

转载请注明出处:http://zhongmingmao.me/2019/05/09/java-concurrent-readwrite-lock/

访问原文「 Java并发 -- ReadWriteLock 」获取最佳阅读体验并参与讨论


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

玻璃笼子

玻璃笼子

[美]尼古拉斯·卡尔 / 杨柳 / 中信出版社 / 2015-11 / 49.00元

这是一本关于自动化的书,它提醒我们自动化对人类的影响,人们心安理得享受技术带来的便利却忽视了,它已经渗透进了生活和工作改变了我们的思维和认知方式。商家在设计程序和应用时,早就把他们的想法埋入了编程和APP中。 卡尔的作品无疑是给我们这个时代灌入了的一剂清醒药。他独特的思考问题角度,犀利甚至略为偏激 的言论再加上丰富的*前沿的科技案例会让人读起来畅快淋漓,且醍醐灌顶,意识到自动化等高科技潜移默......一起来看看 《玻璃笼子》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具