什么是读写锁

平时,我们常见的synchronized和Reentrantlock基本上都是排他锁,这些锁在同一时刻只允许一个线程进行访问,哪怕是读操作。而读写锁是维护了一对锁(一个读锁和一个写锁),通过分离读锁和写锁,使得同一时刻可以允许多个读线程访问,但是在写线程进行访问时,所有的读线程和其他写线程均被阻塞。

读写锁的优点

1. 简化了读写交互场景编程的复杂度:

在常见的开发中,我们经常会定义一个共享的用作缓存的数据结构;比如一个大Map,缓存全部的城市Id和城市name对应关系。这个大Map绝大部分时间提供读服务(根据城市Id查询城市名称等);而写操作占有的时间很少,通常是在服务启动时初始化,然后可以每隔一定时间再刷新缓存的数据。但是写操作开始到结束之间,不能再有其他读操作进来,并且写操作完成之后的更新数据需要对后续的读服务可见。

在没有读写锁支持的时候,如果需要完成上述工作就要使用Java的等待通知机制,就是当写操作开始时,所有晚于写操作的读操作均会进入等待状态,只有写操作完成并进行通知之后,所有等待的读操作才能继续执行(多个写操作之间依靠synchronized关键字进行同步),这样做的目的是使读操作能读取到正确的数据,不会出现脏读。改用读写锁实现上述功能,这只需要在读操作时获取读锁,写操作时获取写锁即可。当写锁被获取到时,后续(非当前操作线程)的读写锁都会被阻塞,写锁释放之后,所有操作继续执行,编程方式相对于使用等待通知机制的实现方式而言。变得简单明了。

2.扩大了程序的吞吐量:

读写锁通过读写使用不同的锁,读操作使用共享锁,写操作使用独占锁的形式,让程序能提供更好的并发性和吞吐量。在读多于写的情况下,读写锁能够提供比排它锁更好的性能。

ReentrantReadWriteLock的特性

特性 说明
公平性选择 支持非公平(默认)和公平的锁获取方式,吞吐量还是非公平优于公平
重进入 该锁支持重进入,以读写线程为例:读线程在获取了读锁之后,能够再次获取读锁。而写线程在获取了写锁之后能够再次获取写锁,同时也可以获取读锁
锁降级 允许从写锁降级为读锁,实现方式时:先获取写锁,再获取读锁,最后释放写锁,此时就会将为读锁。但是,从读锁升级到写锁时不可能的
Condition支持 写锁提供了一个Condition实现,对于写锁来说,该实现的行为与ReentrantLock.newCondition()提供的Condition实现对ReentrantLock所做的行为相同。当然,此Condition只能用于写锁。读锁不支持Condition,readLok().newCondition()会抛出UnsupportedOperationException。
监测 这些方法主要用于监听系统状态,而不是同步控制

使用案例

public class ReentrantReadWriteLockTest {

    private static Map<String, Object> map = new HashMap<>();
private static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private static Lock readLock = rwl.readLock();
private static Lock writeLock = rwl.writeLock(); public static void main(String[] args) { ReentrantReadWriteLockTest reentrantReadWriteLockTest = new ReentrantReadWriteLockTest() ; Executor executor = Executors.newFixedThreadPool(4) ;
executor.execute(() -> {
System.out.println("写锁开始");
reentrantReadWriteLockTest.put("1","1") ;
System.out.println("写锁结束");
});
executor.execute(() -> {
System.out.println("读锁开始");
System.out.println(reentrantReadWriteLockTest.get("4"));
System.out.println("读锁结束");
});
executor.execute(() -> {
System.out.println("写锁开始");
reentrantReadWriteLockTest.put("3", "3") ;
System.out.println("写锁开始");
});
executor.execute(() -> {
System.out.println(reentrantReadWriteLockTest.get("1"));
});
} public void put(String key , String value) {
try {
writeLock.lock();
map.put(key, value);
}finally {
writeLock.unlock();
}
} public Object get(String key) {
try {
readLock.lock();
return map.get(key);
}finally {
readLock.unlock();
}
}
}

Java读写锁(ReentrantReadWriteLock)学习的更多相关文章

  1. Java并发指南10:Java 读写锁 ReentrantReadWriteLock 源码分析

    Java 读写锁 ReentrantReadWriteLock 源码分析 转自:https://www.javadoop.com/post/reentrant-read-write-lock#toc5 ...

  2. 轻松掌握java读写锁(ReentrantReadWriteLock)的实现原理

    转载:https://blog.csdn.net/yanyan19880509/article/details/52435135 前言 前面介绍了java中排它锁,共享锁的底层实现机制,本篇再进一步, ...

  3. [图解Java]读写锁ReentrantReadWriteLock

    图解ReentrantReadWriteLock 如果之前使用过读写锁, 那么可以直接看本篇文章. 如果之前未使用过, 那么请配合我的另一篇文章一起看:[源码分析]读写锁ReentrantReadWr ...

  4. 源码分析— java读写锁ReentrantReadWriteLock

    前言 今天看Jraft的时候发现了很多地方都用到了读写锁,所以心血来潮想要分析以下读写锁是怎么实现的. 先上一个doc里面的例子: class CachedData { Object data; vo ...

  5. Java并发(十):读写锁ReentrantReadWriteLock

    先做总结: 1.为什么用读写锁 ReentrantReadWriteLock? 重入锁ReentrantLock是排他锁,在同一时刻仅有一个线程可以进行访问,但是在大多数场景下,大部分时间都是提供读服 ...

  6. java 可重入读写锁 ReentrantReadWriteLock 详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt206 读写锁 ReadWriteLock读写锁维护了一对相关的锁,一个用于只 ...

  7. 从火车站车次公示栏来学Java读写锁

    Java多线程并发之读写锁 本文主要内容:读写锁的理论:通过生活中例子来理解读写锁:读写锁的代码演示:读写锁总结.通过理论(总结)-例子-代码-然后再次总结,这四个步骤来让大家对读写锁的深刻理解. 本 ...

  8. 读写锁ReentrantReadWriteLock:读读共享,读写互斥,写写互斥

    介绍 DK1.5之后,提供了读写锁ReentrantReadWriteLock,读写锁维护了一对锁:一个读锁,一个写锁.通过分离读锁和写锁,使得并发性相比一般的排他锁有了很大提升.在读多写少的情况下, ...

  9. Java读写锁

    Java读写锁,ReadWriteLock.java接口, RentrantReadWriteLock.java实现.通过读写锁,可以实现读-读线程并发,读-写,写-读线程互斥进行.以前面试遇到一个问 ...

随机推荐

  1. [bzoj] 1030 文本生成器 || AC自动机+dp

    原题 给出n个字符串,求随机生成一个m长度的字符串,有多少个是可辨识的(即出现了n个字符串中的任意字符串) 正难则反 求有多少个不可辨识的,26^m-不可辨识即为答案 f[i][j]表示填到第i个字符 ...

  2. 重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?

    方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性.重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同.参数个数不同或者二者都不同)则视 ...

  3. C#或ASP.NET绘图初探

    C#或ASP.NET的简单绘图 public void ProcessRequest (HttpContext context) { context.Response.ContentType = &q ...

  4. phpstorm 安装

    16 sudo apt-get install python-software-properties 17 sudo add-apt-repository ppa:webupd8team/java 1 ...

  5. Android 百度定位SDKv4.2及6.0_百度定位实例_安卓定位实例

    介绍 由于项目需要.前几天一直在研究百度定位的功能.通过不断的实践终于有结果了.不愿意独享 现在我把我的研究成果和大家分享一下.其实百度的 API 已经相当不错了 这之所以要写出来.一是自己做一个笔记 ...

  6. UVA 11105 Semi-prime H-numbers

    https://vjudge.net/problem/UVA-11105 筛法 #include<cstdio> #include<cstring> #define N 100 ...

  7. bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description ...

  8. [洛谷P1527] [国家集训队]矩阵乘法

    洛谷题目链接:[国家集训队]矩阵乘法 题目背景 原 <补丁VS错误>请前往P2761 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入 ...

  9. 【HDU】6148 Valley Numer 数位DP

    [算法]数位DP [题意]定义V-number为从左到看单位数字未出现先递增后递减现象的数字,求0~N中满足条件的数字个数.T<=200,lenth(n)<=100 [题解]百度之星201 ...

  10. 【BZOJ】1914: [Usaco2010 OPen]Triangle Counting 数三角形

    [题意]给定坐标系上n个点,求能构成的包含原点的三角形个数,n<=10^5. [算法]极角排序 [题解]补集思想,三角形个数为C(n,3)-不含原点三角形. 将所有点极角排序. 对于一个点和原点 ...