@SuppressWarnings("restriction")
public class ReentrantReadWriteLock1 implements ReadWriteLock, java.io.Serializable {
private static final long serialVersionUID = -6992448646407690164L;
private final ReentrantReadWriteLock1.ReadLock readerLock;
private final ReentrantReadWriteLock1.WriteLock writerLock;
final Sync sync; public ReentrantReadWriteLock1() {
this(false);
} public ReentrantReadWriteLock1(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);//写锁和读锁,公用同一个Sync,也就是同一个AQS队列,
writerLock = new WriteLock(this);
} public ReentrantReadWriteLock1.WriteLock writeLock() {
return writerLock;
} public ReentrantReadWriteLock1.ReadLock readLock() {
return readerLock;
} abstract static class Sync extends AbstractQueuedSynchronizer1 {//ReentrantLock有自己的Sync,都继承AQS类,
private static final long serialVersionUID = 6317671515068378041L; static final int SHARED_SHIFT = ;
static final int SHARED_UNIT = ( << SHARED_SHIFT);// 2^16
static final int MAX_COUNT = ( << SHARED_SHIFT) - ;// 2^16-1
static final int EXCLUSIVE_MASK = ( << SHARED_SHIFT) - ;// 2^16-1 static int sharedCount(int c) {//小于2^16=0,等于2^16=1,大于2^16>1,共享锁最大共享线程数=2^16-1,
return c >>> SHARED_SHIFT;// 右移16位,
} static int exclusiveCount(int c) {
return c & EXCLUSIVE_MASK;// 去掉前面16位,
} static final class HoldCounter {
int count = ;
final long tid = getThreadId(Thread.currentThread());
} static final class ThreadLocalHoldCounter extends ThreadLocal<HoldCounter> {
public HoldCounter initialValue() {
return new HoldCounter();//ThreadLocalHoldCounter作为key,new HoldCounter()作为value,
}
} //当前线程持有的可重入读锁的数量。构造函数中初始化。每当线程的读计数下降到0时删除。
private transient ThreadLocalHoldCounter readHolds;//只有一个 private transient HoldCounter cachedHoldCounter;//多个 private transient Thread firstReader = null;
private transient int firstReaderHoldCount; Sync() {
readHolds = new ThreadLocalHoldCounter();//只有一个
setState(getState());
} abstract boolean readerShouldBlock();
abstract boolean writerShouldBlock(); protected final boolean tryRelease(int releases) {//写锁释放
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
int nextc = getState() - releases;// 状态变量的值减1
boolean free = exclusiveCount(nextc) == ;//写锁=0
if (free)//getState()-releases == 0
setExclusiveOwnerThread(null);
setState(nextc);
return free;
} protected final boolean tryAcquire(int acquires) {//WriteLock获取锁,多线程访问
Thread current = Thread.currentThread();
int c = getState();
int w = exclusiveCount(c);//w=0则C=2^16,w!=0则C<2^16,写锁被获取的次数 if (c != ) {//锁里面有线程了重入锁,写锁只要看见state里面有线程就去排队(可能里面有读锁或者写锁), // c!=0,w=0:说明C=2^16的整数倍,说明有读线程获取了锁,
if (w == || current != getExclusiveOwnerThread()) // c!=0,w=0,说明有读锁进去,写锁不进去,其它线程获取了互斥锁(写锁)
return false;//获取锁失败去排队 /*单线程进来,线程安全的。 */ //w!=0&&current=OwnerThread,MAX_COUNT=2^16-1,就去加值,
if (w + exclusiveCount(acquires) > MAX_COUNT)
throw new Error("Maximum lock count exceeded");
//w!=0&&current=OwnerThread,MAX_COUNT=2^16-1,就去加值,
setState(c + acquires);//acquires每次都是从1开始的,C从0开始,所以c,w,acquires不可能大于2^16。
return true;
}
//c=0,锁里面没有线程,就要去抢锁。
//writerShouldBlock:非公平返回false,就去获取锁。
//writerShouldBlock:公平,返回true排队,返回false,就去获取锁。
//获取state成功设置owenerThread=自己,不去排队,获取state失败,去排队。
if (writerShouldBlock() || !compareAndSetState(c, c + acquires))
return false; /*单线程进来,线程安全的。
compareAndSetState(c, c+acquires)可以作为一把锁,synchronized,
别的线程要想进到compareAndSetState包裹的代码里面去,必须重新获取新的c=c+acquires,但是进去if(c!=0)里面去了。
*/ setExclusiveOwnerThread(current);//获得锁。
return true;
} protected final boolean tryReleaseShared(int unused) {// 读锁释放(共享锁),unused没有使用
Thread current = Thread.currentThread();
if (firstReader == current) {
// 如果第一个读者(读线程)是当前线程
// 就把它重入的次数减1
// 如果减到0了就把第一个读者置为空
if (firstReaderHoldCount == )
firstReader = null;
else
firstReaderHoldCount--;
} else {
// 如果第一个读者不是当前线程,一样地,把它重入的次数减1
HoldCounter rh = cachedHoldCounter;//最后获取读锁的HoldCounter
if (rh == null || rh.tid != getThreadId(current))
rh = readHolds.get();//get方法没有时候,就回去创建,有就返回。返回当前线程threadLcoalMap里面的那行记录
int count = rh.count;
if (count <= ) {
readHolds.remove();
if (count <= )
throw unmatchedUnlockException();
}
--rh.count;
}
for (;;) {// 共享锁获取的次数减1,如果减为0了说明完全释放了,才返回true
int c = getState();
int nextc = c - SHARED_UNIT;//减去65536
if (compareAndSetState(c, nextc))
return nextc == ;//读锁完全释放了,
}
} private IllegalMonitorStateException unmatchedUnlockException() {
return new IllegalMonitorStateException("attempt to unlock read lock, not locked by current thread");
} //读锁每次进来加65536,写锁每次进来加1,
protected final int tryAcquireShared(int unused) {//ReadLock获取锁,走这个方法,并发问题,unused没有使用
// 在读写锁模式下,高16位存储的是共享锁(读锁)被获取的次数,低16位存储的是互斥锁(写锁)被获取的次数
Thread current = Thread.currentThread();
int c = getState();//state在AQS类里面,读锁写锁,公用一个Sync AQS state,写锁只能一个进去,另一个写锁进不去,读锁也进不去,
if (exclusiveCount(c) != /*去掉前面16位,*/ && getExclusiveOwnerThread() != current)//state!=0,并且 当前线程没有获取锁。如果写线程获取了锁,state+1就返回-1去排队。
return -;
int r = sharedCount(c);//右移16位, 读锁被获取的次数
//多线程可以进来
if (!readerShouldBlock()/* AQS队列第一个节点写线程跳过,没有第一个节点或者第一个是读线程就进去 */ && r < MAX_COUNT
&& compareAndSetState(c, c + SHARED_UNIT)/* c每次增加65536 */) {
//可以多线程进来,AQS队列没有节点 并且 c是2^16的整数倍=0就是没有写锁,第一个线程进来后只要后面的线程重新获取c就可以进来, // 注意下面对firstReader的处理:firstReader是不会放到readHolds里的
// 这样,在读锁只有一个的情况下,就避免了查找readHolds。
if (r == ) {//r=0,c<2^16,没有读锁
firstReader = current;//获取读锁的线程,Thread
firstReaderHoldCount = ;
} else if (firstReader == current) {//重入锁
firstReaderHoldCount++;
} else {
//先查缓存
HoldCounter rh = cachedHoldCounter;//HoldCounter,缓存前一个线程的HoldCounter(线程id和获取锁次数)
if (rh == null || rh.tid != getThreadId(current))
//ThreadLocal里面get,ThreadLocalHoldCounter。
//当前线程的threadLocals属性的threadLocalMap里面加了一行记录(key=readHolds[ThreadLocalHoldCounter],value=cachedHoldCounter[HoldCounter]),
//其他线程也会在他的threadLocals的threadLocalMap里面加一行记录(key=readHolds[ThreadLocalHoldCounter],value=cachedHoldCounter[HoldCounter]),
//每个线程里面只有一行记录,ThreadLocal是公用的,因为只有一个ThreadLocal,value放的是线程的id和计数器。就这样线程就获取了锁,
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == )//当前线程就是上一次线程,就修改thradLocals
readHolds.set(rh);
rh.count++;//多个读,只有一个firstReader,其余的都是在线程里面的threadLocals里面加了一行记录,重入的次数加1(初始次数为0)
}
return ;//获取了锁
}
//有人在排队
return fullTryAcquireShared(current);
} //在tryAcquireShared中经行了一次快速锁获取,但是由于CAS只能允许一个线程获取锁成功,且读锁是共享的,
//可能存在其他仍然可以获取锁的线程,所以在函数末尾调用函数fullTryAcquireShared来进行死循环的获取锁,
final int fullTryAcquireShared(Thread current) {//获取读锁
HoldCounter rh = null;
for (;;) {//死循环
int c = getState();
if (exclusiveCount(c) != ) {//去掉前面16位!= 0
if (getExclusiveOwnerThread() != current)//相等,就是先获取写锁在获取读锁,
return -;//排队
// 否则,我们持有独占锁;在这里阻塞将导致死锁。
} else if (readerShouldBlock()) {//去掉前面16位= 0,并且AQS队列有第一个节点是写锁不是读锁,
// 确保我们没有重新获取读锁
if (firstReader == current) {
// assert firstReaderHoldCount > 0;
} else {
if (rh == null) {
rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current)) {
rh = readHolds.get();//设置当前线程的threadLocals,key还是readHolds同一个ThreadLocal,
if (rh.count == )//!=0,就说明这个线程之前已经获取一次锁成功了,
readHolds.remove();//从当前线程threadLocals中移除这行记录,
}
}
if (rh.count == )
return -;//排队,
}
} //AQS没有节点,有第一个节点,第一个节点只能是读节点,就去设置threadLcoalMap并且获取锁,
if (sharedCount(c) == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
if (compareAndSetState(c, c + SHARED_UNIT)) {
if (sharedCount(c) == ) {//=0,就说明没有读线程,
firstReader = current;
firstReaderHoldCount = ;
} else if (firstReader == current) {
firstReaderHoldCount++;
} else {
if (rh == null)
rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
rh = readHolds.get();
else if (rh.count == )
readHolds.set(rh);
rh.count++;
cachedHoldCounter = rh; // cache for release
}
return ;//获取了锁
}
}
} final boolean tryWriteLock() {
Thread current = Thread.currentThread();
int c = getState();
if (c != ) {
int w = exclusiveCount(c);
if (w == || current != getExclusiveOwnerThread())
return false;
if (w == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
}
//c=0
if (!compareAndSetState(c, c + ))
return false;
setExclusiveOwnerThread(current);
return true;
} final boolean tryReadLock() {
Thread current = Thread.currentThread();
for (;;) {
int c = getState();
if (exclusiveCount(c) != && getExclusiveOwnerThread() != current)
return false;
int r = sharedCount(c);
if (r == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
if (compareAndSetState(c, c + SHARED_UNIT)) {
if (r == ) {
firstReader = current;
firstReaderHoldCount = ;
} else if (firstReader == current) {
firstReaderHoldCount++;
} else {
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == )
readHolds.set(rh);
rh.count++;
}
return true;
}
}
} protected final boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
} final ConditionObject newCondition() {
return new ConditionObject();
} final Thread getOwner() {
return ((exclusiveCount(getState()) == ) ? null : getExclusiveOwnerThread());
} final int getReadLockCount() {
return sharedCount(getState());
} final boolean isWriteLocked() {
return exclusiveCount(getState()) != ;
} final int getWriteHoldCount() {
return isHeldExclusively() ? exclusiveCount(getState()) : ;
} final int getReadHoldCount() {
if (getReadLockCount() == )
return ; Thread current = Thread.currentThread();
if (firstReader == current)
return firstReaderHoldCount; HoldCounter rh = cachedHoldCounter;
if (rh != null && rh.tid == getThreadId(current))
return rh.count; int count = readHolds.get().count;
if (count == )
readHolds.remove();
return count;
} private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
readHolds = new ThreadLocalHoldCounter();
setState(); // reset to unlocked state
} final int getCount() {
return getState();
}
} static final class NonfairSync extends Sync {
private static final long serialVersionUID = -8159625535654395037L; final boolean writerShouldBlock() {//false获取锁。
return false;
} final boolean readerShouldBlock() {// 非公平读是否要阻塞,true排队,false获取锁。
return apparentlyFirstQueuedIsExclusive();//AQS队列有第一个节点是写锁不是读锁,
}
} static final class FairSync extends Sync {
private static final long serialVersionUID = -2274990926593161451L; final boolean writerShouldBlock() {// 公平写是否要阻塞,true排队,false获取锁。
return hasQueuedPredecessors();
} final boolean readerShouldBlock() {// 公平读是否要阻塞,true排队,false获取锁。
return hasQueuedPredecessors();
}
} public static class ReadLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = -5992448646407690164L;
private final Sync sync; protected ReadLock(ReentrantReadWriteLock1 lock) {// 外部类this
sync = lock.sync;
} public void lock() {//获取读锁,获取的是共享锁,调用sync.acquireShared(AQS的方法),写锁调用sync.acquire(AQS的方法)
try {
sync.acquireShared();
} catch (InterruptedException e) {
e.printStackTrace();
}
} public void lockInterruptibly() throws InterruptedException {
sync.acquireSharedInterruptibly();
} public boolean tryLock() {
return sync.tryReadLock();
} public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireSharedNanos(, unit.toNanos(timeout));
} public void unlock() {
sync.releaseShared();
} public Condition newCondition() {
throw new UnsupportedOperationException();
} public String toString() {
int r = sync.getReadLockCount();
return super.toString() + "[Read locks = " + r + "]";
}
} public static class WriteLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = -4992448646407690164L;
private final Sync sync; protected WriteLock(ReentrantReadWriteLock1 lock) {
sync = lock.sync;
} public void lock() {//获取写锁,写锁的获取逻辑和ReentrantLock一样,失败的加入AQS队列,
try {//读锁调用sync.acquireShared(AQS的方法),写锁调用sync.acquire(AQS的方法)
sync.acquire();//尝试获取锁,获取失败就在AQS阻塞排队
} catch (InterruptedException e) {
e.printStackTrace();
}
} public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly();
} public boolean tryLock() {
return sync.tryWriteLock();//获取读锁,不在AQS类里面,在本Sync类里面,
} public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(, unit.toNanos(timeout));
} public void unlock() {
sync.release();//写锁释放,线程安全,唤醒AQS头结点,
} public Condition newCondition() {
return sync.newCondition();
} public String toString() {
Thread o = sync.getOwner();
return super.toString() + ((o == null) ? "[Unlocked]" : "[Locked by thread " + o.getName() + "]");
} public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
} public int getHoldCount() {
return sync.getWriteHoldCount();
}
} public final boolean isFair() {
return sync instanceof FairSync;
} protected Thread getOwner() {
return sync.getOwner();
} public int getReadLockCount() {
return sync.getReadLockCount();
} public boolean isWriteLocked() {
return sync.isWriteLocked();
} public boolean isWriteLockedByCurrentThread() {
return sync.isHeldExclusively();
} public int getWriteHoldCount() {
return sync.getWriteHoldCount();
} public int getReadHoldCount() {
return sync.getReadHoldCount();
} protected Collection<Thread> getQueuedWriterThreads() {
return sync.getExclusiveQueuedThreads();
} protected Collection<Thread> getQueuedReaderThreads() {
return sync.getSharedQueuedThreads();
} public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
} public final boolean hasQueuedThread(Thread thread) {
return sync.isQueued(thread);
} public final int getQueueLength() {
return sync.getQueueLength();
} protected Collection<Thread> getQueuedThreads() {
return sync.getQueuedThreads();
} public boolean hasWaiters(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer1.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.hasWaiters((AbstractQueuedSynchronizer1.ConditionObject) condition);
} public int getWaitQueueLength(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer1.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitQueueLength((AbstractQueuedSynchronizer1.ConditionObject) condition);
} protected Collection<Thread> getWaitingThreads(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer1.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitingThreads((AbstractQueuedSynchronizer1.ConditionObject) condition);
} public String toString() {
int c = sync.getCount();
int w = Sync.exclusiveCount(c);
int r = Sync.sharedCount(c); return super.toString() + "[Write locks = " + w + ", Read locks = " + r + "]";
} // Thread Id可以被重写
static final long getThreadId(Thread thread) {
return UNSAFE.getLongVolatile(thread, TID_OFFSET);
} private static final sun.misc.Unsafe UNSAFE;
private static final long TID_OFFSET;
static {
try {
UNSAFE = java.security.AccessController
.doPrivileged(new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
public sun.misc.Unsafe run() throws Exception {
Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
for (java.lang.reflect.Field f : k.getDeclaredFields()) {
f.setAccessible(true);
Object x = f.get(null);
if (k.isInstance(x))
return k.cast(x);
}
throw new NoSuchFieldError("the Unsafe");
}
});
Class<?> tk = Thread.class;
TID_OFFSET = UNSAFE.objectFieldOffset(tk.getDeclaredField("tid"));
} catch (Exception e) {
throw new Error(e);
}
} }

ReentrantReadWriteLock源码的更多相关文章

  1. 【Java并发编程】16、ReentrantReadWriteLock源码分析

    一.前言 在分析了锁框架的其他类之后,下面进入锁框架中最后一个类ReentrantReadWriteLock的分析,它表示可重入读写锁,ReentrantReadWriteLock中包含了两种锁,读锁 ...

  2. ReentrantReadWriteLock 源码分析

    ReentrantReadWriteLock  源码分析: 1:数据结构: 成员变量: private final ReentrantReadWriteLock.ReadLock readerLock ...

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

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

  4. 深入浅出ReentrantReadWriteLock源码解析

    读写锁实现逻辑相对比较复杂,但是却是一个经常使用到的功能,希望将我对ReentrantReadWriteLock的源码的理解记录下来,可以对大家有帮助 前提条件 在理解ReentrantReadWri ...

  5. Java并发编程笔记之读写锁 ReentrantReadWriteLock 源码分析

    我们知道在解决线程安全问题上使用 ReentrantLock 就可以,但是 ReentrantLock 是独占锁,同时只有一个线程可以获取该锁,而实际情况下会有写少读多的场景,显然 Reentrant ...

  6. ReentrantReadWriteLock源码分析(一)

    此处源码分析,主要是基于读锁,非公平机制,JDK1.8. 问题: 1.ReentrantReadWriteLock是如何创建读锁与写锁? 2.读锁与写锁的区别是什么? 3.锁的重入次数与获取锁的线程数 ...

  7. Java显式锁学习总结之五:ReentrantReadWriteLock源码分析

    概述 我们在介绍AbstractQueuedSynchronizer的时候介绍过,AQS支持独占式同步状态获取/释放.共享式同步状态获取/释放两种模式,对应的典型应用分别是ReentrantLock和 ...

  8. Java多线程——ReentrantReadWriteLock源码阅读

    之前讲了<AQS源码阅读>和<ReentrantLock源码阅读>,本次将延续阅读下ReentrantReadWriteLock,建议没看过之前两篇文章的,先大概了解下,有些内 ...

  9. 死磕 java同步系列之ReentrantReadWriteLock源码解析

    问题 (1)读写锁是什么? (2)读写锁具有哪些特性? (3)ReentrantReadWriteLock是怎么实现读写锁的? (4)如何使用ReentrantReadWriteLock实现高效安全的 ...

  10. ReentrantReadWriteLock源码分析笔记

    ReentrantReadWriteLock包含两把锁,一是读锁ReadLock, 此乃共享锁, 一是写锁WriteLock, 此乃排它锁. 这两把锁都是基于AQS来实现的. 下面通过源码来看看Ree ...

随机推荐

  1. 2019 学霸君java面试笔试题 (含面试题解析)

      本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.学霸君等公司offer,岗位是Java后端开发,因为发展原因最终选择去了学霸君,入职一年时间了,也成为了面试官 ...

  2. sklearn聚类评价指标

    sklearn中的指标都在sklearn.metric包下,与聚类相关的指标都在sklearn.metric.cluster包下,聚类相关的指标分为两类:有监督指标和无监督指标,这两类指标分别在skl ...

  3. 网页百度地图api,支持位置偏移

    网页百度地图api,支持位置偏移 需加载 jq <style type="text/css"> #allmap {width:100%; height:100%; bo ...

  4. preflight request预检请求

    preflight request预检请求,负责检查是否允许跨域请求,但是注意并不是所有的跨域请求都会发送preflight请求.对与那些幂等的请求,如GET请求,就不会发送preflight请求.只 ...

  5. 微信小程序开发--flex详细解读

    一.结构:flex布局 是由一个大的容器加上多个子元素组成. <view class="container"> <view </view> <v ...

  6. HP服务器重装centeos 6.3红屏错误码 Illegal Opcode

    公司组装一个服务器要装centos 6.3 .出现一个问题 如果自动引导一切正常.如果手动分区重启后就会,红屏错误码 Illegal Opcode. 去网上问度娘各种不靠谱,有时说要 升级BIOS,从 ...

  7. 接口自动化--数据驱动(ddt)

    上次我们提到了unittest单元测试框架,运用单元测试框架unittest进行编写测试用例 但是遇到了一个问题,就是难道我一个测试点中有多个测试用例,我要每一个都要去编写一条测试用例嘛?这实在是太复 ...

  8. python类定义的讲解

    python是怎么定义类的,看了下面的文章大家就会了,不用多说,开始学习. 一.类定义: 复制代码代码如下: class <类名>: <语句> 类实例化后,可以使用其属性,实际 ...

  9. Java多线程编程核心技术-第1章-Java多线程技能-读书笔记

    第 1 章 Java 多线程技能 本章主要内容 线程的启动 如何使线程暂停 如何使线程停止 线程的优先级 线程安全相关的问题 1.1 进程和多线程的概念及线程的优点 进程是操作系统结构的基础:是一次程 ...

  10. VMware下安装Ubuntu虚拟机

    ubuntu系统是以桌面应用为主的.当下最火的linux操作系统,具有实用的界面,并且完全免费. 在Ubuntu的 Linux 世界里,已经不再只是简陋的界面+命令行,而是一款华丽时尚且无比实用的操作 ...