关于AbstractQueuedSynchronizer中的独占锁,请参考ReentrantLock(http://www.cnblogs.com/bjorney/p/8040085.html)

1. ReentrantReadWriteLock

// ReentrantReadWriteLock本身不提供加锁服务,只负责提供读锁和写锁
public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
private final ReentrantReadWriteLock.ReadLock readerLock;
private final ReentrantReadWriteLock.WriteLock writerLock;
final Sync sync; public ReentrantReadWriteLock() {
this(false);
} public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock
= new WriteLock(this);
} public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; } // 写锁
public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; } // 读锁 // 总的读锁计数
public int getReadLockCount() {
return sync.getReadLockCount();
} // 当前线程的写锁计数(当前线程必须占有锁)
public int getWriteHoldCount() {
return sync.getWriteHoldCount();
} // 当前线程的读锁计数
public int getReadHoldCount() {
return sync.getReadHoldCount();
} // 获取所有在SyncQueue中排队的写线程
protected Collection<Thread> getQueuedWriterThreads() {
return sync.getExclusiveQueuedThreads();
} // 获取所有在SyncQueue中排队的读线程
protected Collection<Thread> getQueuedReaderThreads() {
return sync.getSharedQueuedThreads();
} ... ... static final long getThreadId(Thread thread) {
return UNSAFE.getLongVolatile(thread, TID_OFFSET); // tid在Thread类中非volatile
} private static final sun.misc.Unsafe UNSAFE;
private static final long TID_OFFSET;
static {
try {
UNSAFE = sun.misc.Unsafe.getUnsafe();
Class<?> tk = Thread.class;
TID_OFFSET = UNSAFE.objectFieldOffset
(tk.getDeclaredField("tid"));
} catch (Exception e) {
throw new Error(e);
}
} }

2. ReentrantReadWriteLock.ReadLock

public static class ReadLock implements Lock, java.io.Serializable {
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() { // 尝试加读锁
return sync.tryReadLock();
} public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { // 加读锁(在timeOut内等锁)
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
} public void unlock() { // 释放读锁
sync.releaseShared(1);
} ... ...
}

3. ReentrantReadWriteLock.WriteLock

public static class WriteLock implements Lock, java.io.Serializable {
private final Sync sync; protected WriteLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
} public void lock() { // 加写锁
sync.acquire(1);
} public void lockInterruptibly() throws InterruptedException { // 加写锁(可被中断)
sync.acquireInterruptibly(1);
} public boolean tryLock( ) { // 尝试加写锁
return sync.tryWriteLock();
} public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { // 加写锁(在timeOut内等锁)
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
} public void unlock() { // 释放写锁
sync.release(1);
} ... ...
}

4. ReentrantReadWriteLock.Sync

abstract static class Sync extends AbstractQueuedSynchronizer {
static final int SHARED_SHIFT = 16; // state高16位为读锁计数,state低16位为写锁计数
static final int SHARED_UNIT = (1 << SHARED_SHIFT); // 读锁计数 + 1
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1; // 读(写)锁计数 <= 2^16 - 1
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1; // 写锁计数 = state & (2^16 - 1) Sync() {
readHolds = new ThreadLocalHoldCounter();
setState(getState());
} // return 锁状态(锁计数)
final int getCount() { return getState(); } // 总的读锁计数
final int getReadLockCount() {
return sharedCount(getState());
}
static int sharedCount(int c) { return c >>> SHARED_SHIFT; } // 当前线程的写锁计数(当前线程必须占有锁)
final int getWriteHoldCount() {
return isHeldExclusively() ? exclusiveCount(getState()) : 0;
}
static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; } // 当前线程的读锁计数
final int getReadHoldCount() {
if (getReadLockCount() == 0)
return 0; 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 == 0) readHolds.remove();
return count;
} private transient ThreadLocalHoldCounter readHolds; // 当前线程的读锁计数
private transient HoldCounter cachedHoldCounter; // 缓存的线程读锁计数
private transient Thread firstReader = null; // 首个读线程
private transient int firstReaderHoldCount; // 首个读线程的读锁计数

static final class HoldCounter {
int count = 0;
// tid在Thread类中非volatile
// Thread.getId -> UNSAFE.getLongVolatile(Thread.currentThread(), Thread.class.getDeclaredField("tid"))
final long tid = getThreadId(Thread.currentThread());
} static final class ThreadLocalHoldCounter extends ThreadLocal<HoldCounter> {
public HoldCounter initialValue() {
return new HoldCounter(); // {0, currentThreadId}
}
} // 尝试取写锁
protected final boolean tryAcquire(int acquires) {
Thread current = Thread.currentThread();
int c = getState(); /*记录state*/
int w = exclusiveCount(c); // 写锁计数w
if (c != 0) {// 读线程未释放锁 || 当前线程不是锁的独占者
if (w == 0 || current != getExclusiveOwnerThread())
return false; // 取锁失败
// 当前线程已占有锁(Reentrant)
if (w + exclusiveCount(acquires) > MAX_COUNT)
throw new Error("Maximum lock count exceeded");
setState(c + acquires); // 更新锁状态,写锁计数++
return true; // 成功取锁(已占有锁)
}
// state == 0
if (writerShouldBlock() || // false(NonfairSync)|| hasQueuedPredecessors(FairSync)
!compareAndSetState(c, c + acquires)) /*CAS设置state += acquires*/
// CAS(state)失败
return false; // 取锁失败
// CAS(state)成功
setExclusiveOwnerThread(current); // 设置当前线程为锁的独占者
return true; // 成功取锁
} // 尝试抢写锁,不进行writerShouldBlock判断
final boolean tryWriteLock() {
Thread current = Thread.currentThread();
int c = getState();
if (c != 0) {
int w = exclusiveCount(c); // 写锁计数w
// 读线程未释放锁 || 当前线程不是锁的独占者
if (w == 0 || current != getExclusiveOwnerThread())
return false;
// 当前线程已占有锁(Reentrant)
if (w == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
}
if (!compareAndSetState(c, c + 1)) // CAS设置state += 1
// CAS(state)失败
return false; // 抢锁失败
// CAS(state)成功
setExclusiveOwnerThread(current);
return true; // 抢锁成功
} // 尝试取读锁
protected final int tryAcquireShared(int unused) {
Thread current = Thread.currentThread();
int c = getState(); /*记录state*/
// 写线程未释放锁 && 未释放锁的写线程非当前线程(读写线程可为同一线程)
if (exclusiveCount(c) != 0 && getExclusiveOwnerThread() != current)
return -1; // 取锁失败
int r = sharedCount(c); // 读锁计数r
if (!readerShouldBlock() && // apparentlyFirstQueuedIsExclusive(NonfairSync)|| hasQueuedPredecessors(FairSync)
r < MAX_COUNT && // r未超过阈值
compareAndSetState(c, c + SHARED_UNIT)) { /*CAS设置state += SHARED_UNIT*/ // 读锁计数++
// CAS(state)成功
if (r == 0) { // 首个读线程
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) { // 当前线程为首个读线程
firstReaderHoldCount++;
} else { // 当前线程非首个读线程
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current)) // 缓存为空 || 缓存的不是当前线程的读锁计数
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0) // 缓存的是当前线程的读锁计数,而当前线程的读锁计数在上次release时被删除
readHolds.set(rh);
rh.count++;
}
return 1; // 成功取锁
}
// CAS(state)失败
return fullTryAcquireShared(current);
} // 不断尝试取读锁,直到取锁失败(写线程占有锁 || 当前线程的读锁计数为0) || 成功取锁
final int fullTryAcquireShared(Thread current) {
HoldCounter rh = null;
for (;;) {
// 当前线程的读锁计数不为0 && CAS(state)失败将回到此处
int c = getState(); /*记录state*/
if (exclusiveCount(c) != 0) { // 写线程未释放锁
if (getExclusiveOwnerThread() != current) // 当前线程不是锁的独占者
return -1;// 取锁失败
} else if (readerShouldBlock()) {
if (firstReader == current) {
} else {
if (rh == null) {
rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current)) {
rh = readHolds.get();
if (rh.count == 0) // 当前线程的读锁计数为0
readHolds.remove(); // 在线程局部变量中删除当前线程的读锁计数
}
}
if (rh.count == 0) // 当前线程的读锁计数为0
return -1; // 应排队取锁
// 继续尝试取锁
}
}
if (sharedCount(c) == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
if (compareAndSetState(c, c + SHARED_UNIT)) { /*CAS设置state += SHARED_UNIT*/
// CAS(state)成功
if (sharedCount(c) == 0) { // 首个读线程
firstReader = current;
firstReaderHoldCount = 1;
} 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 == 0)
readHolds.set(rh);
rh.count++;
cachedHoldCounter = rh; // cache for release
}
return 1; // 成功取锁
}
// CAS(state)失败
}
} // 尝试抢读锁,不进行readerShouldBlock判断
final boolean tryReadLock() {
Thread current = Thread.currentThread();
for (;;) {
// CAS(state)失败将回到此处
int c = getState(); /*记录state*/
// 写线程未释放锁 && 未释放锁的写线程非当前线程(读写线程可为同一线程)
if (exclusiveCount(c) != 0 && 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)) { /*CAS设置state += SHARED_UNIT*/
// CAS(state)成功
if (r == 0) { // 首个读线程
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) { // 当前线程为首个读线程
firstReaderHoldCount++;
} else { // 当前线程非首个读线程
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
rh.count++; // 当前线程的读锁计数(缓存的线程读锁计数)++
}
return true; // 成功抢锁
}
// CAS(state)失败
}
} // 尝试释放写锁
protected final boolean tryRelease(int releases) {
if (!isHeldExclusively()) // 当前线程未占有锁
throw new IllegalMonitorStateException();
int nextc = getState() - releases;
boolean free = exclusiveCount(nextc) == 0; // 写锁计数是否为0
if (free) // 可释放锁
setExclusiveOwnerThread(null); // 锁的独占者置空
setState(nextc); // 更新锁状态
return free;
} // 尝试释放读锁
protected final boolean tryReleaseShared(int unused) {
Thread current = Thread.currentThread();
if (firstReader == current) { // 当前线程为首个读线程
// assert firstReaderHoldCount > 0;
if (firstReaderHoldCount == 1)
firstReader = null;
else
firstReaderHoldCount--;
} else { // 当前线程非首个读线程
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
rh = readHolds.get();
int count = rh.count;
if (count <= 1) {
readHolds.remove(); // 在线程局部变量中删除当前线程的读锁计数
if (count <= 0)
throw unmatchedUnlockException();
}
--rh.count; // 当前线程的读锁计数(缓存的线程读锁计数)--
}
for (;;) {
// CAS(state)失败将回到此处
int c = getState(); /*记录state*/
int nextc = c - SHARED_UNIT; // 读锁计数--
if (compareAndSetState(c, nextc)) /*CAS设置state = nextc*/
// CAS(state)成功
return nextc == 0;
// CAS(state)失败
}
} ... ...
} static final class NonfairSync extends Sync {
final boolean writerShouldBlock() { // 写线程永远可以抢锁
return false;
}
final boolean readerShouldBlock() { // SyncQueue排队的第一个节点(head.next)为写节点占锁时必须排队
return apparentlyFirstQueuedIsExclusive();
}
} static final class FairSync extends Sync {
final boolean writerShouldBlock() { // SyncQueue中下个待唤醒节点不是当前线程时必须排队
return hasQueuedPredecessors();
}
final boolean readerShouldBlock() { // SyncQueue中下个待唤醒节点不是当前线程时必须排队
return hasQueuedPredecessors();
}
}

5. AbstractQueuedSynchronizer

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {

    // 尝试取读锁,取锁失败则排队等锁
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0) // 尝试取锁失败
doAcquireShared(arg); // 排队等锁
} // 排队等读锁
private void doAcquireShared(int arg) {
final Node node = addWaiter(Node.SHARED); // 在SyncQueue尾部添加读节点(共享锁:Node.SHARED)
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg); // 尝试取读锁
if (r >= 0) { // tryAcquireShared成功
setHeadAndPropagate(node, r); // 置SyncQueue头结点为node,唤醒node后置位读节点
p.next = null; // help GC
if (interrupted)
selfInterrupt();
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt
())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
} // 置SyncQueue头结点为node,唤醒node后置位读节点
private void setHeadAndPropagate(Node node, int propagate) {
Node h = head;
setHead(node); // 置SyncQueue头结点为node
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
Node s = node.next; // s为node后置节点
if (s == null || s.isShared()) // s为空 || s为读节点
doReleaseShared(); // 唤醒s:s若取消排队(被中断 || 超时),则可能唤醒写节点
}
} // 尝试释放读锁,成功释放锁时unpark successor
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) { // 成功释放锁
doReleaseShared(); // 唤醒后置位节点
return true;
}
// 未释放锁
return false;
} // unpark successor
private void doReleaseShared() {
for (;;) {
// CAS(head.waitStatus)失败将回到此处
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) { // head后置位节点等待被唤醒
// 可能其它读线程正在同步设置head.waitStatus
// A线程执行完毕后tryReleaseShared,锁被释放,B线程抢锁成功(未参与排队)
// B线程执行完毕后tryReleaseShared,A、B同步doReleaseShared
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) // CAS设置head.waitStatus = 0
// CAS(head.waitStatus)失败
continue;
// CAS(head.waitStatus)成功
unparkSuccessor(h);
// 若此时是读线程在setHeadAndPropagate中释放后置位读节点,则可能唤醒写节点:
// 被唤醒的写节点若tryAcquire失败,则将在shouldParkAfterFailedAcquire中重置head.waitStatus = Node.SIGNAL
}
// ws == 0:head后置位节点为空 || head后置节点已被其它线程唤醒
// 可能其它读线程正在同步设置head.waitStatus
// A线程执行完毕后tryReleaseShared,锁被释放,B线程抢锁失败(未参与排队)
// B线程在SyncQueue末尾添加新节点,并在shouldParkAfterFailedAcquire中同步设置head.waitStatus = Node.SIGNAL
else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) // CAS设置head.waitStatus = Node.PROPAGATE
// CAS(head.waitStatus)失败
continue;
// CAS(head.waitStatus)成功
}
if (h == head) // 后置位读节点被唤醒并成为head后,将继续唤醒后置读节点
break;
}
} // 尝试取读锁,取锁失败则排队等锁(可被中断)
public final void acquireSharedInterruptibly(int arg) throws InterruptedException;
// 排队等读锁(可被中断)
private void doAcquireSharedInterruptibly(int arg) throws InterruptedException; // 尝试取读锁,取锁失败则排队等锁(nanosTimeout时间内)
public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException;
// 排队等读锁(nanosTimeout时间内)
private boolean doAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException; // SyncQueue排队的第一个节点(head.next)为写节点
final boolean apparentlyFirstQueuedIsExclusive() {
Node h, s;
return (h = head) != null && // head不为空
(s = h.next) != null && // head存在后置节点
!s.isShared() && // head.next以独占方式取锁(为写节点)
s.thread != null; // head.next未取消排队
} // 获取所有在SyncQueue中排队的写线程
public final Collection<Thread> getExclusiveQueuedThreads(); // 获取所有在SyncQueue中排队的读线程
public final Collection<Thread> getSharedQueuedThreads(); ... ...
}

ReentrantReadWriteLock (读写锁)源码分析的更多相关文章

  1. java并发锁ReentrantReadWriteLock读写锁源码分析

    1.ReentrantReadWriterLock 基础 所谓读写锁,是对访问资源共享锁和排斥锁,一般的重入性语义为如果对资源加了写锁,其他线程无法再获得写锁与读锁,但是持有写锁的线程,可以对资源加读 ...

  2. 多线程高并发编程(4) -- ReentrantReadWriteLock读写锁源码分析

    背景: ReentrantReadWriteLock把锁进行了细化,分为了写锁和读锁,即独占锁和共享锁.独占锁即当前所有线程只有一个可以成功获取到锁对资源进行修改操作,共享锁是可以一起对资源信息进行查 ...

  3. java读写锁源码分析(ReentrantReadWriteLock)

    读锁的调用,最终委派给其内部类 Sync extends AbstractQueuedSynchronizer /** * 获取读锁,如果写锁不是由其他线程持有,则获取并立即返回: * 如果写锁被其他 ...

  4. ReentrantLock 源码分析以及 AQS (一)

    前言 JDK1.5 之后发布了JUC(java.util.concurrent),用于解决多线程并发问题.AQS 是一个特别重要的同步框架,很多同步类都借助于 AQS 实现了对线程同步状态的管理. A ...

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

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

  6. [源码分析]读写锁ReentrantReadWriteLock

    一.简介 读写锁. 读锁之间是共享的. 写锁是独占的. 首先声明一点: 我在分析源码的时候, 把jdk源码复制出来进行中文的注释, 有时还进行编译调试什么的, 为了避免和jdk原生的类混淆, 我在类前 ...

  7. 锁对象-Lock: 同步问题更完美的处理方式 (ReentrantReadWriteLock读写锁的使用/源码分析)

    Lock是java.util.concurrent.locks包下的接口,Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题,我 ...

  8. 源码分析:ReentrantReadWriteLock之读写锁

    简介 ReentrantReadWriteLock 从字面意思可以看出,是和重入.读写有关系的锁,实际上 ReentrantReadWriteLock 确实也是支持可重入的读写锁,并且支持公平和非公平 ...

  9. 深入理解读写锁—ReadWriteLock源码分析

    转载:https://blog.csdn.net/qq_19431333/article/details/70568478 ReadWriteLock管理一组锁,一个是只读的锁,一个是写锁.读锁可以在 ...

  10. 源码分析:升级版的读写锁 StampedLock

    简介 StampedLock 是JDK1.8 开始提供的一种锁, 是对之前介绍的读写锁 ReentrantReadWriteLock 的功能增强.StampedLock 有三种模式:Writing(读 ...

随机推荐

  1. border-image

    一.border-image的兼容性 border-image可以说是CSS3中的一员大将,将来一定会大放光彩,其应用潜力真的是非常的惊人.可惜目前支持的浏览器有限,仅 Firefox3.5,chro ...

  2. LOJ 6057 - [HNOI2016]序列 加强版再加强版

    Description 给定一个长度为 \(n\le 3*10^6\) 的序列 \(q\le 10^7\) 次询问每次求区间 \([l,r]\) 的所有子区间的最小值的和 询问随机 Solution ...

  3. wikioi 1245最小的N个和

    2013-09-08 10:12 LRJ的算法竞赛入门经典训练指南里有类似的题,原题要难很多,p189页 读入A,B两组中的所有数后,建立N个有序表: A1+B1<A2+B1<A3+B1& ...

  4. 关于chkrootkit 检查 INFECTED: Possible Malicious Linux.Xor.DDoS installed

    chkrootkit检测时,发现一个Xor.DDoS内容,内容如下...Searching for Linux.Xor.DDoS ... INFECTED: Possible Malicious Li ...

  5. python3 面向对象补充

    f = People('egon',18,'male') 非函数hasattr # hasattr(f,'name')getattr # getattr(f,'name')setattr # seta ...

  6. 解决小米/红米手机无法进行jdwp调试的问题

    问题描述:在逆向一个app,研究环境是一台红米2,需要使用jdwp接口,也就是ddms下面这个界面: 但神奇的是,同一台主机上,模拟器的进程可以显示在ddms界面上,红米2确一个进程都没有显示出来.c ...

  7. bayer转dng实现过程记录

    前言 项目中需要将imx185出来的raw数据转成dng格式,一开始认为很简单的事情,后面才发现还是挺复杂的!!!首先考虑的是不写任何代码,直接用adobe提供的转换工具来转,结果发现,不仅是adob ...

  8. k8s通过secret管理敏感信息

    应用启动过程中可能需要一些敏感信息,比如访问数据库的用户名密码或者秘钥.将这些信息直接保存在容器镜像中显然不妥,Kubernetes 提供的解决方案是 Secret. Secret 会以密文的方式存储 ...

  9. C#获取屏幕大小或任务栏大小

    C#获取屏幕大小或任务栏大小http://www.cnblogs.com/chlyzone/archive/2012/11/05/2754601.html

  10. AVR单片机中的EEPROM

    1.EEPROM介绍 Electrically Erasable Programmable Read Only Memory 电气可拭除可编程只读存储器 发展过程:ROM – > PROM –& ...