@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. 经典SQL语句使用方法大全(自留用)

    一.基础 1.说明:创建数据库CREATE DATABASE database-name2.说明:删除数据库drop database dbname3.说明:备份sql server--- 创建 备份 ...

  2. Python——pip快速下载第三方库到指定环境

    pip install Scikit-learn --target=C:/Users/Jery/PycharmProjects/play/venv/Lib/site-packages -i https ...

  3. 【转载】C#使用typeof运算符获取对象变量的具体类型Type

    在C#的实际类型操作过程中,有时候需要通过typeof方法获取对象的类型对应的Type变量即具体类型,例如在获取DataTable中某一列的具体数据类型的时候,我们就会用到typeof方法来获取具体的 ...

  4. 你家的APS系统有这些功能吗?排程系统功能盘点

    随着企业规模不断扩大,在经营管理方面会面临各种各样的问题,为了帮助解决此类问题,很多公司都会引入APS高级排程系统帮助进行生产管理的优化. APS系统针对的管理目标是 改善库存控制,大幅降低原料与中间 ...

  5. Java枚举的用法和原理深入

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10843644.html 一:枚举的用法 1.定义和组织常量 在JDK1.5之前,我们定义常量都是:publi ...

  6. React源码 ReactDOM.render

    在 react 当中,主要创建更新的有三种方式 1.ReactDOM.render || hydrate  这两个api都是要把这个应用第一次渲染到我们页面上面,展现出来整个应用的样子的过程,这就是初 ...

  7. PAT 乙级 1042.字符统计 C++/Java

    题目来源 请编写程序,找出一段给定文字中出现最频繁的那个英文字母. 输入格式: 输入在一行中给出一个长度不超过 1000 的字符串.字符串由 ASCII 码表中任意可见字符及空格组成,至少包含 1 个 ...

  8. LengthFieldBasedFrameDecoder

    LengthFieldBasedFrameDecoder 详解 疯狂创客圈 Java 分布式聊天室[ 亿级流量]实战系列之 -31[ 博客园 总入口 ] 文章目录 LengthFieldBasedFr ...

  9. IDEA中常用的一些设置

    一.idea常用设置1.报错级别    idea默认不会像eclipse一样需要ctrl+s进行保存,并且在保存时会进行编译(可以在File>Settings>Build,Executio ...

  10. 数据库中的gt,ge,lt,le的区别

    eq相等   ne.neq不相等,   gt大于, lt小于 gte.ge大于等于   lte.le 小于等于   not非   mod求模   is [not] div by是否能被某数整除   i ...