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, 可重入读写锁,包括公平锁和非公平锁,相比较公平锁而言,非公平锁有更好的吞吐量,但可能会出现队列里的线程无限期地推迟一个或多个读线程或写线程的情况, ...
随机推荐
- 理解 Java 序列化
一.什么是序列化 序列化是一种对象持久化的手段.类通过实现 java.io.Serializable 接口以启用其序列化功能. 序列化:把对象转换为字节序列的过程. 反序列化:把字节序列恢复为对象的过 ...
- leetcode-12双周赛-1243-数组变换
题目描述: 自己的提交: class Solution: def transformArray(self, arr: List[int]) -> List[int]: if len(arr) & ...
- JMeter4.0 IF Controller
推荐使用 __jexl3 函数生成 if controller判断条件 举个栗子: 1. 假如条件为 "${demo}" == "test" 2. 在If Co ...
- java poi导出Excel合并单元格并设置边框
import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCellStyle; i ...
- action通信机制
当service通信不能很好的完成任务时候, actionlib则可以比较适合实现长时间的通信过程, actionlib通信过程可以随时被查看过程进度, 也可以终止请求, 这样的一个特性, 使得它在一 ...
- delphi dll调用问题
dll传递string实现方法 delphi中dll传递string的实现方法: dll项目uses第一个引用sharemem单元; 调用的项目uses第一个引用sharemem单元; 调用的单元us ...
- Python 工匠
https://github.com/piglei/one-python-craftsman/blob/master/zh_CN/7-two-tips-on-loop-writing.md
- 2.5 webpack 进阶
配置分离 code splitting 异步加载 理解 webpack chunk webpack 调试 2.5.1 配置分离 在大型项目中,可能 webpack.config.js 会变得越来越臃肿 ...
- Redis启动Sentinel出现警告的解决
Redis 3.0.7版本启动时出现警告的解决办法 7283:M 12 Mar 12:13:33.749 # WARNING: The TCP backlog setting of 511 canno ...
- vue组件通信之父组件主动获取子组件数据和方法
ref 可以用来获取到dom节点,如果在组件中应用,也可以用来获取子组件的数据和方法. 比如,我定义了一个home组件,一个head组件,home组件中引用head组件. 此时,home组件是head ...