JUC 一 ReentrantReadWriteLock
java.util.concurrent.locks
ReentrantLock
是独占锁,一种相对比较保守的锁策略,在这种情况下任何“读/读”、“读/写”、“写/写”操作都不能同时发生
ReentrantReadWriteLock
读写锁内部又分为读锁和写锁,读锁可以在没有写锁的时候被多个线程同时持有,写锁是独占的。
在读锁和写锁的获取过程中支持中断 。Condition只有在写锁中用到(读锁是不支持Condition)
简介
一个线程要想同时持有写锁和读锁,必须先获取写锁再获取读锁;写锁可以“降级”为读锁;读锁不能“升级”为写锁。
线程进入读锁的前提条件(在线程持有读锁的情况下,该线程不能取得写锁):
- 没有其他线程的写锁
线程进入写锁的前提条件( 在线程持有写锁的情况下,该线程可以继续获取读锁):
- 没有其他线程的读锁
- 没有其他线程的写锁
读写锁有以下三个重要的特性:
(1)公平选择性:支持非公平(默认)和公平的锁获取方式,吞吐量还是非公平优于公平。
(2)重进入:读锁和写锁都支持线程重进入。
(3)锁降级:遵循获取写锁、获取读锁再释放写锁的次序,写锁能够降级成为读锁。
基本方法
public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {}
ReentrantReadWriteLock实现了接口ReadWriteLock,该接口提供了两个方法,一个用于获取读锁,另一个用于获取写锁:
public interface ReadWriteLock {
/**
* Returns the lock used for reading.
*
* @return the lock used for reading
*/
Lock readLock();
/**
* Returns the lock used for writing.
*
* @return the lock used for writing
*/
Lock writeLock();
}
ReentrantReadWriteLock
//支持非公平(默认)和公平的锁获取方式,吞吐量还是非公平优于公平
public ReentrantReadWriteLock() {
this(false);
}
public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
public int getReadLockCount():当前读锁被获取的次数,但不是占用该锁的线程数,也就是说,一个线程如果n次获取该锁,该方法返回n,而不是1。
public int getReadHoldCount():当前线程获取读锁的次数。
public boolean isWriteLocked():判断写锁是否被获取。
public int getWriteHoldCount():当前线程获取写锁的次数。
ReadLock
public static class ReadLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = -5992448646407690164L;
//持有的AQS对象
private final Sync sync;
protected ReadLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
//获取共享锁
public void lock() {
sync.acquireShared(1);
}
//获取共享锁(响应中断)
public void lockInterruptibly() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
//尝试获取共享锁
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
//释放锁
public void unlock() {
sync.releaseShared(1);
}
//新建条件
public Condition newCondition() {
throw new UnsupportedOperationException();
}
public String toString() {
int r = sync.getReadLockCount();
return super.toString() +
"[Read locks = " + r + "]";
}
}
示例
public class ReadWriteLock {
static ReadWriteLock lock=new ReentrantReadWriteLock();
static Lock read=lock.readLock();
static Lock write=lock.writeLock();
static HashMap<String, Object> map=new HashMap<String, Object>();
static Object get(String key){
read.lock();
try {
return map.get(key);
} finally {
read.unlock();
}
}
static void put(String key,Object value){
write.lock();
try {
map.put(key, value);
} finally {
write.unlock();
}
}
static void clear(){
write.lock();
try {
map.clear();
} finally {
write.unlock();
}
}
}
锁降级示例
锁降级是指把持住(当前拥有的)写锁,再获取到读锁,随后释放(先前拥有的)写锁的过程。
static Object putAndget(String key,Object value){
write.lock();
try {
read.lock();
map.put(key, value);
} finally {
write.unlock();
}
try {
return map.get(key);
} finally {
read.unlock();
}
}
JUC 一 ReentrantReadWriteLock的更多相关文章
- 6.JUC之ReentrantReadWriteLock
一.概述: Java纪年1.5年,ReentrantReadWriteLock诞生于JUC,此后,国人一般称它为读写锁.人如其名,他就是一个可重入锁,同时他还是一个读写锁 a)跟ReentrantLo ...
- 最强Java并发编程详解:知识点梳理,BAT面试题等
本文原创更多内容可以参考: Java 全栈知识体系.如需转载请说明原处. 知识体系系统性梳理 Java 并发之基础 A. Java进阶 - Java 并发之基础:首先全局的了解并发的知识体系,同时了解 ...
- Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock
概要 Java的JUC(java.util.concurrent)包中的锁包括"独占锁"和"共享锁".在“Java多线程系列--“JUC锁”02之 互斥锁Ree ...
- Java - "JUC" ReentrantReadWriteLock
Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock ReadWriteLock 和 ReentrantReadWriteLock介绍 ReadWriteLo ...
- 【Java并发】JUC—ReentrantReadWriteLock有坑,小心读锁!
好长一段时间前,某些场景需要JUC的读写锁,但在某个时刻内读写线程都报超时预警(长时间无响应),看起来像是锁竞争过程中出现死锁(我猜).经过排查项目并没有能造成死锁的可疑之处,因为业务代码并不复杂(仅 ...
- 【JUC】JDK1.8源码分析之ReentrantReadWriteLock(七)
一.前言 在分析了锁框架的其他类之后,下面进入锁框架中最后一个类ReentrantReadWriteLock的分析,它表示可重入读写锁,ReentrantReadWriteLock中包含了两种锁,读锁 ...
- 【JUC】JDK1.8源码分析之ReentrantReadWriteLock
重入锁ReentrantLock是排他锁,排他锁在同一时刻仅有一个线程可以进行访问,但是在大多数场景下,大部分时间都是提供读服务,而写服务占有的时间较少.然而读服务不存在数据竞争问题,如果一个线程在读 ...
- JUC——线程同步锁(ReentrantReadWriteLock读写锁)
读写锁简介 所谓的读写锁值得是两把锁,在进行数据写入的时候有一个把“写锁”,而在进行数据读取的时候有一把“读锁”. 写锁会实现线程安全同步处理操作,而读锁可以被多个对象读取获取. 读写锁:ReadWr ...
- 【JUC源码解析】ReentrantReadWriteLock
简介 ReentrantReadWriteLock, 可重入读写锁,包括公平锁和非公平锁,相比较公平锁而言,非公平锁有更好的吞吐量,但可能会出现队列里的线程无限期地推迟一个或多个读线程或写线程的情况, ...
随机推荐
- 每天一个Linux常用命令 cp命令
Linux cp命令主要用于复制文件或目录 -a:此选项通常在复制目录时使用,它保留链接.文件属性,并复制目录下的所有内容.其作用等于dpR参数组合. -d:复制时保留链接.这里所说的链接相当于Win ...
- 编写Android.mk中的LOCAL_SRC_FILES的终极技巧(转)
转自:http://blog.csdn.net/fu_zk/article/details/12836431 问题的引入 在使用NDK编译C/C++项目的过程中,免不了要编写Android.mk文件, ...
- php高版本安装ecshop错误解决方法
1.Strict Standards: Non-static method cls_image::gd_version() should not be called statically in F:\ ...
- Dart编程实例 - 第一个Dart程序
Dart编程实例 - 第一个Dart程序 main() { print("Hello World!"); } 本文转自:http://codingdict.com/article/ ...
- INNODB存储引擎之缓冲池
以下的资料总结自:官方文档和<MySQL技术内幕-INNODB存储引擎>一书. 对INNODB存储引擎缓冲池的那一段描述来自博文:http://www.ywnds.com/?p=9886说 ...
- php手册的一些思考
函数手册一定要认真看,很多用法都不太清楚: array array_merge ( array $array1 [, array $... ] ) array_merge() 将一个或多个数组的单 ...
- delphi下运行vbscript脚本
简单一个vb脚本,功能为打开被限制的注册表.Set wso = CreateObject("WScript.Shell")wso.RegWrite "HKEY_CURRE ...
- PHP 图形验证码
一段生成图形验证码的代码,向原创作者致谢. 1.将以下代码保存为 txm.php ,注:直接运行该页面是没有结果的,要用另一页面引用,请看步骤2 <?php session_start(); $ ...
- Android 读取<meta-data>元素的数据
在AndroidManifest.xml中,<meta-data>元素可以作为子元素,被包含在<activity>.<application> .<servi ...
- 其它课程中的python---5、Pandas处理数据和读取数据
其它课程中的python---5.Pandas处理数据和读取数据 一.总结 一句话总结: 记常用和特例:慢慢慢慢的就熟了,不用太着急,慢慢来 库的使用都很简单:就是库的常用函数就这几个,后面用的时候学 ...