【Java多线程】ReentrantReadWriteLock
概述
ReentrantReadWriteLock是Lock的另一种实现方式,ReentrantLock是一个排他锁,同一时间只允许一个线程访问,而ReentrantReadWriteLock允许多个读线程同时访问,但不允许写线程和读线程、写线程和写线程同时访问。相对于排他锁,提高了并发性。在实际应用中,大部分情况下对共享数据(如缓存)的访问都是读操作远多于写操作,这时ReentrantReadWriteLock能够提供比排他锁更好的并发性和吞吐量。
所谓读写锁,是对访问资源共享锁和排斥锁,一般的重入性语义为 如果对资源加了写锁,其他线程无法再获得写锁与读锁,但是持有写锁的线程,可以对资源加读锁(锁降级);如果一个线程对资源加了读锁,其他线程可以继续加读锁。
线程进入读锁的前提条件:
没有其他线程的写锁,
没有写请求或者有写请求,但调用线程和持有锁的线程是同一个。
线程进入写锁的前提条件:
没有其他线程的读锁
没有其他线程的写锁
使用
示例一:利用重入来执行升级缓存后的锁降级

1 class CachedData {
2 Object data;
3 volatile boolean cacheValid; //缓存是否有效
4 ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
5
6 void processCachedData() {
7 rwl.readLock().lock(); //获取读锁
8 //如果缓存无效,更新cache;否则直接使用data
9 if (!cacheValid) {
10 // Must release read lock before acquiring write lock
11 //获取写锁前须释放读锁
12 rwl.readLock().unlock();
13 rwl.writeLock().lock();
14 // Recheck state because another thread might have acquired
15 // write lock and changed state before we did.
16 if (!cacheValid) {
17 data = ...
18 cacheValid = true;
19 }
20 // Downgrade by acquiring read lock before releasing write lock
21 //锁降级,在释放写锁前获取读锁
22 rwl.readLock().lock();
23 rwl.writeLock().unlock(); // Unlock write, still hold read
24 }
25
26 use(data);
27 rwl.readLock().unlock(); //释放读锁
28 }
29 }

示例二:使用 ReentrantReadWriteLock 来提高 Collection 的并发性
通常在 collection 数据很多,读线程访问多于写线程并且 entail 操作的开销高于同步开销时尝试这么做。

1 class RWDictionary {
2 private final Map<String, Data> m = new TreeMap<String, Data>();
3 private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
4 private final Lock r = rwl.readLock(); //读锁
5 private final Lock w = rwl.writeLock(); //写锁
6
7 public Data get(String key) {
8 r.lock();
9 try { return m.get(key); }
10 finally { r.unlock(); }
11 }
12 public String[] allKeys() {
13 r.lock();
14 try { return m.keySet().toArray(); }
15 finally { r.unlock(); }
16 }
17 public Data put(String key, Data value) {
18 w.lock();
19 try { return m.put(key, value); }
20 finally { w.unlock(); }
21 }
22 public void clear() {
23 w.lock();
24 try { m.clear(); }
25 finally { w.unlock(); }
26 }
27 }

实现原理
ReentrantReadWriteLock 也是基于AQS实现的,它的自定义同步器(继承AQS)需要在同步状态(一个整型变量state)上维护多个读线程和一个写线程的状态,使得该状态的设计成为读写锁实现的关键。如果在一个整型变量上维护多种状态,就一定需要“按位切割使用”这个变量,读写锁将变量切分成了两个部分,高16位表示读,低16位表示写。
转自:https://www.cnblogs.com/zaizhoumo/p/7782941.html,https://blog.csdn.net/prestigeding/article/details/53286756
【Java多线程】ReentrantReadWriteLock的更多相关文章
- java多线程----ReentrantReadWriteLock
package com.test; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks ...
- Java多线程——ReentrantReadWriteLock源码阅读
之前讲了<AQS源码阅读>和<ReentrantLock源码阅读>,本次将延续阅读下ReentrantReadWriteLock,建议没看过之前两篇文章的,先大概了解下,有些内 ...
- Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock
概要 Java的JUC(java.util.concurrent)包中的锁包括"独占锁"和"共享锁".在“Java多线程系列--“JUC锁”02之 互斥锁Ree ...
- Java多线程(五) Lock接口,ReentranctLock,ReentrantReadWriteLock
在JDK5里面,提供了一个Lock接口.该接口通过底层框架的形式为设计更面向对象.可更加细粒度控制线程代码.更灵活控制线程通信提供了基础.实现Lock接口且使用得比较多的是可重入锁(Reentrant ...
- java多线程7:ReentrantReadWriteLock
真实的多线程业务开发中,最常用到的逻辑就是数据的读写,ReentrantLock虽然具有完全互斥排他的效果(即同一时间只有一个线程正在执行lock后面的任务), 这样做虽然保证了实例变量的线程安全性, ...
- 40个Java多线程问题总结
前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...
- Java多线程系列--“JUC锁”03之 公平锁(一)
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
- Java多线程系列--“JUC锁”04之 公平锁(二)
概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...
- Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例
概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...
- Java多线程系列--“JUC锁”01之 框架
本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--“JUC锁”01之 框架02. Java多线程系列--“JUC锁”02之 互斥锁Reentrant ...
随机推荐
- Django 学习笔记(五) --- Ajax 传输数据
人生苦短 ~ Tips:仅适用于 Python 3+(反正差别不大,py2 改改也能用).因为据 Python 之父 Guido van Rossum 说会在 2020 年停止对 Python 2 的 ...
- netty源码解解析(4.0)-11 Channel NIO实现-概览
结构设计 Channel的NIO实现位于io.netty.channel.nio包和io.netty.channel.socket.nio包中,其中io.netty.channel.nio是抽象实 ...
- CentOS 7 安装 .Net Core 2.0 详细步骤
轰轰烈烈的Core 热潮,从部署环境开始.参照了网上不少前辈的教程,也遇到不少的坑,这边做个完整的笔记. 一.构建.Net core 2的应用程web发布,因为是用来测试centos上的core 环境 ...
- HTML 中获取现在时间,实时时间获取
JavaScript Date 对象 Date 对象用于处理日期与实际. 创建 Date 对象: var now = new Date(). 方法 描述 getDate() 从 Date 对象 ...
- EF select 匿名类 问题
连续两次被相同问题困扰. 一.举例 var query=db.StudentScore.Where(r=> r.SubjectId==subjectId).Select(g=>new {S ...
- Hadoop专有名词
Hadoop专有名词 一. HDFS 二. MapReduce 1.MRAppMaster:MapReduce Application Master 负责整个过程调度和协调的 2.MapTask:在M ...
- 【协议】3、HTTP 协议入门
HTTP 协议是互联网的基础协议,也是网页开发的必备知识,最新版本 HTTP/2 更是让它成为技术热点. 本文介绍 HTTP 协议的历史演变和设计思路. 一.HTTP/0.9 HTTP 是基于 TCP ...
- 【Dubbo&&Zookeeper】2、 windows平台dubbo-admin管理平台搭建
一.前言 dubbo的使用,其实只需要有注册中心,消费者,提供者这三个就可以使用了,但是并不能看到有哪些消费者和提供者,为了更好的调试,发现问题,解决问题,因此引入dubbo-admin.通过dubb ...
- 使用iconv进行编码gb2312转utf8 转码失败的坑
iconv 编码gb2312转utf8 转码失败的坑 使用背景 项目中使用thrift进行C#程序调用c++接口,其中的协议是通过json进行传输的,由于默认thrift使用utf8进行传输,而C#和 ...
- CSS属性之position讲解
postion 属性定义了一个元素在页面布局中的位置以及对周围元素的影响.该属性共有5个值: position: static position: inherit position: relative ...