内容简介:ReadWriteLock不支持锁升级,readLock还没有释放,无法获取writeLock,导致
- 理论上,利用 管程 和 信号量 可以解决所有并发问题,但JUC提供了很多 工具 类, 细分场景优化性能,提升易用性
- 针对 读多写少 的并发场景,JUC提供了 读写锁 ,即ReadWriteLock
读写锁
- 读写锁是一种广泛使用的 通用技术 ,并非 Java 所特有
-
所有读写锁都遵守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 」获取最佳阅读体验并参与讨论
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Java并发系列—并发编程基础
- [Java并发-17-并发设计模式] Immutability模式:如何利用不变性解决并发问题?
- JAVA并发编程之并发模拟工具
- Java并发系列—并发编程的挑战
- Core Java 并发:理解并发概念
- [Java并发-11] 并发容器的使用
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。