读写锁接口:ReadWriteLock,它的具体实现类为:ReentrantReadWriteLock

使用场景:

对于一个资源,读读能共存,读写不能共存,写写不能共存。

锁降级:从写锁变成读锁;

锁升级:从读锁变成写锁。

ReentrantReadWriteLock不支持锁升级,支持锁降级

ReadWriteLock rtLock = new ReentrantReadWriteLock();
rtLock.readLock().lock();
System.out.println("get readLock.");
rtLock.writeLock().lock();
System.out.println("blocking");

会死锁

ReadWriteLock rtLock = new ReentrantReadWriteLock();
rtLock.writeLock().lock();
System.out.println("writeLock"); rtLock.readLock().lock();
System.out.println("get read lock");

不会死锁

案例应用:

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; public class CacheDemo {
/**
* 缓存器,这里假设需要存储1000左右个缓存对象,按照默认的负载因子0.75,则容量=750,大概估计每一个节点链表长度为5个
* 那么数组长度大概为:150,又有雨设置map大小一般为2的指数,则最近的数字为:128
*/
private Map<String, Object> map = new HashMap<>(128);
private ReadWriteLock rwl = new ReentrantReadWriteLock();
public static void main(String[] args) { }
public Object get(String id){
Object value = null;
rwl.readLock().lock();//首先开启读锁,从缓存中去取
try{
value = map.get(id);
if(value == null){ //如果缓存中没有释放读锁,上写锁
rwl.readLock().unlock();
rwl.writeLock().lock();
try{
if(value == null){ //防止多写线程重复查询赋值
value = "redis-value"; //此时可以去数据库中查找,这里简单的模拟一下
}
rwl.readLock().lock(); //加读锁降级写锁,不明白的可以查看上面锁降级的原理与保持读取数据原子性的讲解
}finally{
rwl.writeLock().unlock(); //释放写锁
}
}
}finally{
rwl.readLock().unlock(); //最后释放读锁
}
return value;
}
}

如果不使用锁降级功能,如先释放写锁,然后获得读锁,在这个get过程中,可能会有其他线程竞争到写锁 或者是更新数据 则获得的数据是其他线程更新的数据,可能会造成数据的污染,即产生脏读的问题。

最新文章

  1. 用于灰度变换的一些实用的M函数
  2. NSXMLParser读取XML文件并将数据显示到TableView上
  3. 鸟哥的linux私房菜学习记录之账号管理与权限设定
  4. CSS控制div宽度最大宽度/高度和最小宽度/高度
  5. python实现雅虎拍卖后台自动回复卖家消息
  6. 为什么使用Redis
  7. JPA + SpringData 操作数据库 ---- 深入了解 SpringData
  8. 老男孩Python全栈开发(92天全)视频教程 自学笔记03
  9. 为什么要进行URL编码
  10. 树莓派3B(2)- 配置多个wifi,自动寻找可用网络
  11. Spring Boot 2.x (八):日志框架的使用
  12. Vue(二)简单入门
  13. 009_关闭linux的THP
  14. [LeetCode&amp;Python] Problem 118. Pascal&#39;s Triangle
  15. 《JavaScript高级教程》学习笔记一、变量和数据类型
  16. JDBC连接SQLServer出现的异常
  17. 大数据处理-Bitmap
  18. jboss 5.1 启动问题解决
  19. 简单的dp加贪心
  20. 使用gdb调试

热门文章

  1. appuim操作webview控件
  2. vue组件 $children,$refs,$parent的使用
  3. 初学HBase的几个问题
  4. jquery淡入淡出轮播图
  5. BZOJ2023: [Usaco2005 Nov]Ant Counting 数蚂蚁(dp)
  6. atm-interface-shopping
  7. JZOJ 5184. 【NOIP2017提高组模拟6.29】Gift
  8. JZOJ 5456. 【NOIP2017提高A组冲刺11.6】奇怪的队列
  9. Python知识点入门笔记——基本控制流程
  10. python语言介绍