读写锁接口: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过程中,可能会有其他线程竞争到写锁 或者是更新数据 则获得的数据是其他线程更新的数据,可能会造成数据的污染,即产生脏读的问题。

java中的读/写锁的更多相关文章

  1. java中ReentrantReadWriteLock读写锁的使用

    Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. 读写锁:分为读 ...

  2. Java中的读写锁

    一.读写锁 1.初识读写锁 a)Java中的锁——Lock和synchronized中介绍的ReentrantLock和synchronized基本上都是排它锁,意味着这些锁在同一时刻只允许一个线程进 ...

  3. 22、Java并发性和多线程-Java中的读/写锁

    以下内容转自http://ifeve.com/read-write-locks/: 相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些.假设你的程序中涉及到对一些共享资源 ...

  4. 【练习】Java中的读文件,文件的创建,写文件

    前言 大家好,给大家带来Java中的读文件,文件的创建,写文件的概述,希望你们喜欢 读文件 public static void read(String path,String filename){ ...

  5. Java中的读文件,文件的创建,写文件

    前言 大家好,我是 Vic,今天给大家带来Java中的读文件,文件的创建,写文件的概述,希望你们喜欢 示意图 读文件 public static void read(String path,Strin ...

  6. Java 并发包中的读写锁及其实现分析

    1. 前言 在Java并发包中常用的锁(如:ReentrantLock),基本上都是排他锁,这些锁在同一时刻只允许一个线程进行访问,而读写锁在同一时 刻可以允许多个读线程访问,但是在写线程访问时,所有 ...

  7. java多线程:并发包中ReentrantReadWriteLock读写锁的原理

    一:读写锁解决的场景问题--->数据的读取频率远远大于写的频率的场景,就可以使用读写锁.二:读写锁的结构--->用state一个变量.将其转化成二进制,前16位为高位,标记读线程获取锁的次 ...

  8. java多线程:并发包中ReentrantReadWriteLock读写锁的锁降级模板

    写锁降级为读锁,但读锁不可升级或降级为写锁. 锁降级是为了让当前线程感知到数据的变化. //读写锁 private ReentrantReadWriteLock lock=new ReentrantR ...

  9. java并发编程-读写锁

    最近项目中需要用到读写锁 读写锁适用于读操作多,写操作少的场景,假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁.在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以 ...

随机推荐

  1. IOS 模仿有storyboard的项目控制器的创建

    ● 先加载storyboard文件(Test是storyboard的文件名) UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@ ...

  2. POJ 3041 Asteroids (对偶性,二分图匹配)

    题目:POJ 3041 Asteroids http://poj.org/problem?id=3041 分析: 把位置下标看出一条边,这显然是一个二分图最小顶点覆盖的问题,Hungary就好. 挑战 ...

  3. POJ 1742 Coins(多重背包,优化)

    <挑战程序设计竞赛>上DP的一道习题. 很裸的多重背包.下面对比一下方法,倍增,优化定义,单调队列. 一开始我写的倍增,把C[i]分解成小于C[i]的2^x和一个余数r. dp[i][j] ...

  4. 【转】iOS开发4:关闭键盘

    在 iOS 程序中当想要在文本框中输入数据,轻触文本框会打开键盘.对于 iPad 程序,其键盘有一个按钮可以用来关闭键盘,但是 iPhone 程序中的键盘却没有这样的按钮,不过我们可以采取一些方法关闭 ...

  5. 2017.12.24 Java序列化你不知道的事(二)

    1 序列化允许重构 序列化允许一定数量的类变种,甚至重构之后也是如此,ObjectInputStream 仍可以很好地将其读出来. Java Object Serialization 规范可以自动管理 ...

  6. ubuntu or centos 网卡无法启动

    [root@seasoned-bro:/home/daeh0f]# /etc/init.d/network restart Restarting network (via systemctl): Jo ...

  7. JSON对象转成formData对象,formData对象转成JSON对象

    在向后端请求时,如果上传的数据里存在file文件对象,需要用到表单提交,这时候我们需要将JSON对象,转成formData对象,具体见代码 const formData = new FormData( ...

  8. python_52_函数返回值2

    def test1(x,y): print(x,y) test1(1,2)#位置参数调用,按顺序来,与形参一一对应 test1(y=1,x=2)#输出为2 1,不是1 2.关键字参数调用按关键字,不按 ...

  9. 张量 (tensor) 是什么?

    对于大部分已经熟练的数学和物理工作者, 这实在是一个极为基础的问题. 但这个问题在我刚接触张量时也困扰了我很久. 张量的那么多定义, 究竟哪些是对的? (显然都是对的. ) 它们的关系是什么? 我尽可 ...

  10. 搭建Nginx反向代理做内网域名转发

    由于公司内网有多台服务器的 http 服务要映射到公司外网静态 IP,如果用路由的端口映射来做,就只能一台内网服务器的 80 端口映射到外网 80 端口,其他服务器的 80 端口只能映射到外网的非 8 ...