关于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. socket编程 ------ 建立 TCP 服务器和客户端流程(阻塞方式)

    服务器端: 服务器端先创建一个socket,然后把这个socket绑定到端口上,接着让它向tcp/ip协议栈请求一个监听服务并创建一个accept队列来接受客户端请求. void creat_tcpS ...

  2. 7月18号day10总结

    今天学习过程和小结 今天学会了用git从GitHub上克隆代码然后打包成jar包,然后在idea程序中引入这个jar包的依赖来使用jar包中的程序. 通过这个中的网址: 在Git Bash Here中 ...

  3. 使用eclipse插件创建一个web project

    使用eclipse插件创建一个web project 首先创建一个Maven的Project如下图 我们勾选上Create a simple project (不使用骨架) 这里的Packing 选择 ...

  4. 记录一次Nginx跳转报错的问题

    错误信息如下: An error occurred. Sorry, the page you are looking for is currently unavailable. Please try ...

  5. C#网络编程基本字段---IPAddress、IPEndPoint

    命名空间: using System.Net; PAddress类提供了对IP地址的转换.处理等功能.其Parse方法可将IP地址字符串转换为IPAddress实例. 如:IPAddress ip = ...

  6. 【BZOJ】1708: [Usaco2007 Oct]Money奶牛的硬币

    [算法]DP [题解] 如果每个排列算一种,则令f[i]表示凑成面值为i的方案数,容易推出f[i]+=f[i-a[j]]. 现在是每个组合才算一种,令f[i][j]第二维表示只使用前j种面值,f[i] ...

  7. 【洛谷 P2346】四子连棋(状态压缩,搜索)

    其实这题可以直接二进制状压做,1表示黑棋,0表示白棋,另外记录下2个空点的位置就行了. 具体看代码(冗长): #include <iostream> #include <cstdio ...

  8. bzoj 1951 lucas crt 费马小定理

    首先假设输入的是n,m 我们就是要求m^(Σ(c(n,i) i|n)) mod p 那么根据费马小定理,上式等于 m^(Σ(c(n,i) i|n) mod  (p-1)) mod p 那么问题的关键就 ...

  9. [转]在树莓派上搭建LAMP服务

    之前介绍过树莓派上LNMP环境的搭建方法,本文将详细介绍如何在树莓派上配置LAMP服务. 为LAMP,是最流行的服务器配置之一,LAMP的含义是: Linux - 操作系统 Apache - 网络服务 ...

  10. [Leetcode Week10]Minimum Time Difference

    Minimum Time Difference 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/minimum-time-difference/desc ...