ReentrantReadWriteLock
ReentrantReadWriteLock 这个对象,有两个内部类,readLock和writeLock,都有一个aqs的属性sync,实例化的时候,获取的是从ReentrantReadWriteLock自己的重写的内部类sync继承了aqs
看readLock的lock()方法
RWlock 的 内部类sync 继承了aqs之后,对state进行了设计,后16位用来表示exlusiveCount,排他的数目。前16位用来表示sharedCount,共享的数目。readLock 的 Lock 调用的是 sync.acquireShared(1),这是aqs的方法,
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
其中,tryAcquireShared是RWLock自己重写了的
用意是:试着获取共享锁,如果获取成功,返回的是正数,如果获取失败,返回的是-1,
逻辑是:
如果exlusiveCount不为0,说明此时有人使用排它锁,而且排它锁的线程不是当前线程,所以不能重入,那么现在的试图获取共享锁的操作是失败的
如果以上不成立,那么,说明可以获取共享锁,如果用cas添加sharedcount成功,那么返回1
否则,进入full啥啥啥方法,逻辑和本方法差不多,只不过在for循环中,为了弥补cas miss,其实是个延迟加载
看readLock的unlock()方法
public void unlock() {
sync.releaseShared(1);
}
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
其中,tryReleaseShared是RWLOCK重写的,tryReleaseShared的逻辑是,获取sharedstate,减一,返回剩下的sharedstate是否等于0,如果不为0,不执行doReleaseShared方法,否则执行
doReleaseShared是AQS的,逻辑是很熟悉的:将head节点的后继节点唤醒。现在是readlock获取到锁之后的unlock,那么挂起线程的列表中绝不会有readlock的申请者,因为是共享的,所以试图获取读锁的线程不会被挂起。所以挂起的线程都是
写锁,那么现在读锁全部释放,唤醒写锁线程也是非常合理的。
看WriteLock的lock()方法
public void lock() {
sync.acquire(1);
}
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
其实还是正常的获取锁的逻辑:尝试获取,如果获取到了,就设置state,exlusiveThread等待,然后往下走,如果获取不到就把线程挂起到队列里
关键是尝试获取的逻辑不同,交给不同的子类sync重写
RWLOCK的tryAcquire的逻辑是:
protected final boolean tryAcquire(int acquires) {
Thread current = Thread.currentThread();
int c = getState();
int w = exclusiveCount(c);
if (c != 0) {
// (Note: if c != 0 and w == 0 then shared count != 0)
if (w == 0 || current != getExclusiveOwnerThread())
return false;
if (w + exclusiveCount(acquires) > MAX_COUNT)
throw new Error("Maximum lock count exceeded");
// Reentrant acquire
setState(c + acquires);
return true;
}
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires))
return false;
setExclusiveOwnerThread(current);
return true;
}
先不看具体逻辑,试想一个,如果一个写锁可以获取,那么前提应该是,没有读锁,没有任何别的写锁,也就是如果有写锁,只能是自己,这也是c != 0中的第一个条件判断的,其他的判断都是判断有没有其他写锁了,这个和普通的独占锁是一样的。
看WriteLock的unlock()方法
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
还是一样的逻辑,try方法自己重写,其他方法继承,
protected final boolean tryRelease(int releases) {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
int nextc = getState() - releases;
boolean free = exclusiveCount(nextc) == 0;
if (free)
setExclusiveOwnerThread(null);
setState(nextc);
return free;
}
逻辑也很简单,减去state上的数目,因为exlusive的是后16位,所以直接减就行了,然后看看后16位是不是0,如果是的话返回真,不是的返回假。返回真的话,就可以唤醒挂起的线程,这个时候的挂起线程就是等待的写线程。
ReentrantReadWriteLock的更多相关文章
- 【Java并发编程实战】-----“J.U.C”:ReentrantReadWriteLock
ReentrantLock实现了标准的互斥操作,也就是说在某一时刻只有有一个线程持有锁.ReentrantLock采用这种独占的保守锁直接,在一定程度上减低了吞吐量.在这种情况下任何的"读/ ...
- 架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock
ReentrantLock 有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级. this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决 ...
- 【JUC】JDK1.8源码分析之ReentrantReadWriteLock(七)
一.前言 在分析了锁框架的其他类之后,下面进入锁框架中最后一个类ReentrantReadWriteLock的分析,它表示可重入读写锁,ReentrantReadWriteLock中包含了两种锁,读锁 ...
- Lock、ReentrantLock、synchronized、ReentrantReadWriteLock使用
先来看一段代码,实现如下打印效果: 1 2 A 3 4 B 5 6 C 7 8 D 9 10 E 11 12 F 13 14 G 15 16 H 17 18 I 19 20 J 21 22 K 23 ...
- Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock
概要 Java的JUC(java.util.concurrent)包中的锁包括"独占锁"和"共享锁".在“Java多线程系列--“JUC锁”02之 互斥锁Ree ...
- ReentrantReadWriteLock读写锁详解
一.读写锁简介 现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁.在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源:但是如果一个线 ...
- ReentrantReadWriteLock类和ReentrantLock类的区别
Java.util.concurrent.locks包定义了两个锁类,ReentrantLock和ReentrantReadWriteLock类. 当有很多线程都从某个数据结构中读取数据而很少有线程对 ...
- 多线程之ReentrantReadWriteLock
java5以后在java.util.concurrent包下,有很多的并发类,可以让我们摆脱java5时,笨重的写法来满足多线程,而且提供了更加丰富的使用场景能力 其中,在locks包下,提供了 Re ...
- Java中的显示锁 ReentrantLock 和 ReentrantReadWriteLock
在Java1.5中引入了两种显示锁,分别是可重入锁ReentrantLock和可重入读写锁ReentrantReadWriteLock.它们分别实现接口Lock和ReadWriteLock.(注意:s ...
- java ReentrantReadWriteLock
// read and write lock is mutual exclusion lock //Listing 7-3. Using ReadWriteLock to Satisfy a Dict ...
随机推荐
- android -------- 颜色的半透明效果配置
最近有朋友问我 Android 背景颜色的半透明效果配置,我网上看资料,总结了一下, 开发中也是常常遇到的,所以来写篇博客 常用的颜色值格式有: RGB ARGB RRGGBB AA ...
- selenium 简单粗暴的定位方法
- 【PowerDesigner】【4】连接数据库并生成ER图
文字版: 1,File→Reverse Engineer→Database...., 2,新窗口database reverse engineering打开后,填写名称(Model name),选择数 ...
- 使用maven构建一个web项目
使用maven构建一个web项目 首先建立一个maven项目(关于环境配置上节有详细过程): 1)-->右键new,-->project ...
- ActiveMQ 事务和XA
1. 客户端怎样显式地使用事务? producer 开启事务(代码片段): ActiveMQSession session = (ActiveMQSession)connection.createSe ...
- provider和consumer配置参数的优先级
<dubbo:service>和<dubbo:reference>存在一些相同的参数,例如:timeout,retries等,那么哪个配置的优先级高呢? consumer合并u ...
- 这些你都了解么------程序员"跳槽"法则
篇头语: “跳槽”这个词是从我报了"软件工程"这个专业后就已经开始听说的词了, 在大学中老师上课也会常说:“等你们参加工作以后,工资低不怕,没事就跳槽,之后工资就高了”: 我相信听 ...
- Linux查看某个命令属于哪个包
有时修我们需要某个命令但其没有安装,提供该命令的包名也与命令名相差很大直接查找命令名找不到包,如rexec. 此时我们就非常需要这样一个工具:可以根据最终的命令查找提供该命令的软件包. 类型 命令 说 ...
- input实时监听
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- 通过css 实现“瀑布流”
.hot_list{-webkit-column-count: 2; -moz-column-count: 2; column-count: 2; -moz-column-gap:7px; -webk ...