JDK 8 ReentrantReadWriteLock 源码详解(详细注释版)
1. 类定义和基本属性
public class ReentrantReadWriteLock
implements ReadWriteLock, java.io.Serializable {
// 序列化版本号
private static final long serialVersionUID = -6992448646407690164L;
/**
* 读锁实例
* 提供共享访问模式
*/
private final ReentrantReadWriteLock.ReadLock readerLock;
/**
* 写锁实例
* 提供独占访问模式
*/
private final ReentrantReadWriteLock.WriteLock writerLock;
/**
* 同步器,ReentrantReadWriteLock的核心实现
* 继承自AQS,管理读写锁的状态
*/
final Sync sync;
/**
* 默认构造方法
* 创建一个非公平的ReentrantReadWriteLock
*
* 构造过程:
* 1. 创建Sync实例(默认非公平)
* 2. 创建读锁和写锁实例
* 3. 建立完整的读写锁体系
*/
public ReentrantReadWriteLock() {
this(false); // 默认使用非公平锁
}
/**
* 指定公平策略的构造方法
* @param fair 是否使用公平锁
*
* 公平性说明:
* - 公平锁:按照请求锁的顺序获得锁
* - 非公平锁:允许插队,性能更好
* - 读锁和写锁共享同一个公平性设置
*/
public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
/**
* 获取读锁
* @return 读锁实例
*/
public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; }
/**
* 获取写锁
* @return 写锁实例
*/
public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
/**
* 同步器抽象基类
* 继承自AbstractQueuedSynchronizer
* 管理读写锁的复杂状态
*/
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 6317671515068378041L;
/**
* 状态字段的位数定义
*
* 状态字段(state)被分为两部分:
* - 高16位:读锁计数(共享锁)
* - 低16位:写锁计数(独占锁)
*
* 这种设计允许同时跟踪读锁和写锁的状态
*/
static final int SHARED_SHIFT = 16; // 共享锁位移量
static final int SHARED_UNIT = (1 << SHARED_SHIFT); // 共享锁单位值
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1; // 最大计数值
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1; // 独占锁掩码
/**
* 从状态字段中提取读锁计数
* 通过无符号右移获取高16位
* @param c 状态值
* @return 读锁计数
*/
static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
/**
* 从状态字段中提取写锁计数
* 通过掩码获取低16位
* @param c 状态值
* @return 写锁计数
*/
static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
/**
* 线程本地变量,用于存储每个线程的读锁重入计数
*
* 设计目的:
* - 跟踪每个线程持有的读锁数量
* - 支持读锁的可重入性
* - 避免竞争和同步开销
*
* 数据结构:
* - 使用ThreadLocal实现线程隔离
* - 每个线程维护自己的计数器
*/
static final class HoldCounter {
int count = 0; // 读锁计数
final long tid = getThreadId(Thread.currentThread()); // 线程ID
/**
* 递增计数
* @return 递增后的值
*/
final int tryInc() {
int c = count;
if (c < 0) // 检查溢出
throw new Error("Maximum lock count exceeded");
return count = c + 1;
}
}
/**
* 线程本地持有计数器
* 继承自ThreadLocal,提供线程本地存储
*/
static final class ThreadLocalHoldCounter
extends ThreadLocal<HoldCounter> {
/**
* 初始化方法
* 为每个线程创建新的HoldCounter
* @return 新的HoldCounter实例
*/
public HoldCounter initialValue() {
return new HoldCounter();
}
}
/**
* 线程本地持有计数器实例
* 用于跟踪每个线程的读锁持有情况
*/
private transient ThreadLocalHoldCounter readHolds;
/**
* 第一个读线程的持有计数器缓存
* 优化:避免频繁的ThreadLocal访问
*/
private transient HoldCounter cachedHoldCounter;
/**
* 第一个获取读锁的线程
* 用于优化单个读线程的场景
*/
private transient Thread firstReader = null;
/**
* 第一个读线程的持有计数
* 与firstReader配合使用
*/
private transient int firstReaderHoldCount;
/**
* 构造方法
* 初始化ThreadLocal持有计数器
*/
Sync() {
readHolds = new ThreadLocalHoldCounter();
setState(getState()); // ensures visibility of readHolds
}
/**
* 获取线程ID的优化方法
* 使用sun.misc.Unsafe直接获取线程ID
* 避免Thread.getId()的同步开销
* @param thread 线程
* @return 线程ID
*/
static final long getThreadId(Thread thread) {
return UNSAFE.getLongVolatile(thread, TID_OFFSET);
}
/**
* 尝试获取写锁(非公平方式)
* @param acquires 获取许可数
* @return 如果获取成功返回true,否则返回false
*
* 获取过程:
* 1. 检查是否有读锁持有者
* 2. 检查写锁是否可重入
* 3. 如果可以获取,更新状态并设置独占线程
*/
final boolean tryWriteLock() {
Thread current = Thread.currentThread();
int c = getState();
if (c != 0) {
int w = exclusiveCount(c);
if (w == 0 || current != getExclusiveOwnerThread())
return false;
if (w == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
}
if (!compareAndSetState(c, c + 1))
return false;
setExclusiveOwnerThread(current);
return true;
}
/**
* 尝试获取读锁(非公平方式)
* @param acquires 获取许可数
* @return 如果获取成功返回true,否则返回false
*
* 获取过程:
* 1. 检查是否有写锁持有者(且不是当前线程)
* 2. 增加读锁计数
* 3. 更新线程本地计数器
*/
final boolean tryReadLock() {
Thread current = Thread.currentThread();
for (;;) {
int c = getState();
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)) {
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;
}
}
}
/**
* 判断当前线程是否是第一个读线程
* @return 如果是返回true,否则返回false
*/
final boolean isFirstReader() {
return firstReader == Thread.currentThread();
}
/**
* 获取第一个读线程的持有计数
* @return 持有计数
*/
final int getFirstReaderHoldCount() {
return firstReader == Thread.currentThread() ? firstReaderHoldCount : 0;
}
/**
* 获取指定线程的读锁持有计数
* @param t 线程
* @return 持有计数
*/
final int getReadHoldCount(Thread t) {
if (t == null)
throw new NullPointerException();
if (isFirstReader())
return firstReaderHoldCount;
HoldCounter rh = cachedHoldCounter;
if (rh != null && rh.tid == getThreadId(t))
return rh.count;
rh = readHolds.get();
return rh == null ? 0 : rh.count;
}
/**
* 检查是否应该阻塞写锁获取
* 公平锁和非公平锁有不同的实现
* @return 如果应该阻塞返回true,否则返回false
*/
abstract boolean writerShouldBlock();
/**
* 检查是否应该阻塞读锁获取
* 公平锁和非公平锁有不同的实现
* @return 如果应该阻塞返回true,否则返回false
*/
abstract boolean readerShouldBlock();
/**
* 尝试获取写锁
* @param acquires 获取许可数
* @return 如果获取成功返回true,否则返回false
*/
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;
}
/**
* 尝试释放写锁
* @param releases 释放许可数
* @return 如果完全释放返回true,否则返回false
*/
protected final boolean tryRelease(int releases) {
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
int nextc = getState() - releases;
boolean free = exclusiveCount(nextc) == 0;
if (free)
setExclusiveOwnerThread(null);
setState(nextc);
return free;
}
/**
* 尝试获取读锁
* @param unused 未使用参数
* @return 如果获取成功返回true,否则返回false
*/
protected final boolean tryAcquireShared(int unused) {
Thread current = Thread.currentThread();
int c = getState();
if (exclusiveCount(c) != 0 &&
getExclusiveOwnerThread() != current)
return -1;
int r = sharedCount(c);
if (!readerShouldBlock() &&
r < MAX_COUNT &&
compareAndSetState(c, c + SHARED_UNIT)) {
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 1;
}
return fullTryAcquireShared(current);
}
/**
* 完整的读锁获取尝试
* 处理CAS失败和阻塞检查的情况
* @param current 当前线程
* @return 获取结果
*/
final int fullTryAcquireShared(Thread current) {
HoldCounter rh = null;
for (;;) {
int c = getState();
if (exclusiveCount(c) != 0) {
if (getExclusiveOwnerThread() != current)
return -1;
} else if (readerShouldBlock()) {
// Make sure we're not acquiring read lock reentrantly
if (firstReader == current) {
// assert firstReaderHoldCount > 0;
} else {
if (rh == null) {
rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current)) {
rh = readHolds.get();
if (rh.count == 0)
readHolds.remove();
}
}
if (rh.count == 0)
return -1;
}
}
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 = 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;
}
}
}
/**
* 尝试释放读锁
* @param unused 未使用参数
* @return 如果完全释放返回true,否则返回false
*/
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 (;;) {
int c = getState();
int nextc = c - SHARED_UNIT;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
/**
* 创建未匹配解锁异常
* @return IllegalMonitorStateException实例
*/
private IllegalMonitorStateException unmatchedUnlockException() {
return new IllegalMonitorStateException(
"attempt to unlock read lock, not locked by current thread");
}
/**
* 获取写锁持有线程
* @return 持有写锁的线程,如果未被持有则返回null
*/
protected final Thread getOwner() {
// Must read state before owner to ensure memory consistency
return ((exclusiveCount(getState()) == 0) ?
null :
getExclusiveOwnerThread());
}
/**
* 获取读锁持有计数
* @return 读锁持有计数
*/
protected final int getReadLockCount() {
return sharedCount(getState());
}
/**
* 判断是否持有写锁
* @return 如果持有写锁返回true,否则返回false
*/
protected final boolean isWriteLocked() {
return exclusiveCount(getState()) != 0;
}
/**
* 判断当前线程是否持有写锁
* @return 如果当前线程持有写锁返回true,否则返回false
*/
protected final boolean isWriteLockedByCurrentThread() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
/**
* 获取写锁重入计数
* @return 重入计数
*/
protected final int getWriteHoldCount() {
return isWriteLockedByCurrentThread() ? exclusiveCount(getState()) : 0;
}
// Unsafe相关字段和方法
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);
}
}
}
/**
* 非公平同步器实现
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = -8159625535654395037L;
/**
* 写锁不应该阻塞(非公平)
* 允许写锁插队
* @return 总是返回false
*/
final boolean writerShouldBlock() {
return false; // writers can always barge
}
/**
* 读锁不应该阻塞(非公平)
* 允许读锁插队
* @return 总是返回false
*/
final boolean readerShouldBlock() {
return apparentlyFirstQueuedIsExclusive();
}
}
/**
* 公平同步器实现
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -2274990926593161451L;
/**
* 写锁应该阻塞(公平)
* 检查等待队列中是否有前驱节点
* @return 如果应该阻塞返回true,否则返回false
*/
final boolean writerShouldBlock() {
return hasQueuedPredecessors();
}
/**
* 读锁应该阻塞(公平)
* 检查等待队列中是否有前驱节点
* @return 如果应该阻塞返回true,否则返回false
*/
final boolean readerShouldBlock() {
return hasQueuedPredecessors();
}
}
2. 读锁实现(详细注释)
/**
* 读锁实现类
* 提供共享锁语义
*/
public static class ReadLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = -5992448646407690164L;
/**
* 关联的ReentrantReadWriteLock实例
*/
private final Sync sync;
/**
* 构造方法
* @param lock 关联的ReentrantReadWriteLock
*/
protected ReadLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
/**
* 获取读锁
* 如果写锁被其他线程持有,当前线程会阻塞
*
* 获取过程:
* 1. 尝试直接获取读锁
* 2. 如果获取失败,加入等待队列
* 3. 阻塞当前线程直到被唤醒
* 4. 被唤醒后重新尝试获取读锁
*
* 可重入性:
* - 同一线程可以多次获取读锁
* - 每次获取都会增加读锁计数
* - 每次释放都会减少读锁计数
* - 只有当所有读锁都释放后,写锁才能获取
*/
public void lock() {
sync.acquireShared(1); // 调用AQS的共享锁获取方法
}
/**
* 获取读锁(可中断)
* 与lock()不同的是,此方法响应中断
*
* 中断处理:
* - 如果线程在等待过程中被中断,会抛出InterruptedException
* - 线程可以被优雅地中止
*
* @throws InterruptedException 如果线程被中断
*/
public void lockInterruptibly() throws InterruptedException {
sync.acquireSharedInterruptibly(1); // 调用AQS的可中断共享锁获取方法
}
/**
* 尝试获取读锁(非阻塞)
* 立即返回,不会阻塞当前线程
*
* 获取结果:
* - 如果读锁可用,立即获取并返回true
* - 如果读锁不可用,立即返回false
*
* 使用场景:
* - 避免线程阻塞
* - 实现超时控制
* - 检查锁的状态
*
* @return 如果获取成功返回true,否则返回false
*/
public boolean tryLock() {
return sync.tryReadLock(); // 调用sync的tryReadLock方法
}
/**
* 尝试获取读锁(带超时)
* 如果读锁不可用,等待指定时间
*
* 超时处理:
* - 在指定时间内获取锁,返回true
* - 超时未获取到锁,返回false
* - 等待过程中可被中断
*
* @param timeout 等待时间
* @param unit 时间单位
* @return 如果获取成功返回true,否则返回false
* @throws InterruptedException 如果线程被中断
*/
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
/**
* 释放读锁
* 减少读锁计数,如果为0则完全释放读锁
*
* 释放过程:
* 1. 减少读锁计数
* 2. 如果计数为0,唤醒等待的写锁线程
* 3. 允许写锁获取
*
* 异常处理:
* - 如果当前线程没有持有读锁,抛出IllegalMonitorStateException
*/
public void unlock() {
sync.releaseShared(1); // 调用AQS的共享锁释放方法
}
/**
* 读锁不支持Condition
* @throws UnsupportedOperationException 总是抛出此异常
*/
public Condition newCondition() {
throw new UnsupportedOperationException();
}
/**
* 返回读锁的字符串表示
* @return 字符串表示
*/
public String toString() {
int r = sync.getReadLockCount();
return super.toString() +
"[Read locks = " + r + "]";
}
}
3. 写锁实现(详细注释)
/**
* 写锁实现类
* 提供独占锁语义
*/
public static class WriteLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = -4992448646407690164L;
/**
* 关联的ReentrantReadWriteLock实例
*/
private final Sync sync;
/**
* 构造方法
* @param lock 关联的ReentrantReadWriteLock
*/
protected WriteLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
/**
* 获取写锁
* 如果读锁或写锁被其他线程持有,当前线程会阻塞
*
* 获取过程:
* 1. 尝试直接获取写锁
* 2. 如果获取失败,加入等待队列
* 3. 阻塞当前线程直到被唤醒
* 4. 被唤醒后重新尝试获取写锁
*
* 可重入性:
* - 同一线程可以多次获取写锁
* - 每次获取都会增加写锁计数
* - 每次释放都会减少写锁计数
* - 只有当写锁计数为0时,其他线程才能获取读锁或写锁
*/
public void lock() {
sync.acquire(1); // 调用AQS的独占锁获取方法
}
/**
* 获取写锁(可中断)
* 与lock()不同的是,此方法响应中断
*
* 中断处理:
* - 如果线程在等待过程中被中断,会抛出InterruptedException
* - 线程可以被优雅地中止
*
* @throws InterruptedException 如果线程被中断
*/
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1); // 调用AQS的可中断独占锁获取方法
}
/**
* 尝试获取写锁(非阻塞)
* 立即返回,不会阻塞当前线程
*
* 获取结果:
* - 如果写锁可用,立即获取并返回true
* - 如果写锁不可用,立即返回false
*
* 使用场景:
* - 避免线程阻塞
* - 实现超时控制
* - 检查锁的状态
*
* @return 如果获取成功返回true,否则返回false
*/
public boolean tryLock() {
return sync.tryWriteLock(); // 调用sync的tryWriteLock方法
}
/**
* 尝试获取写锁(带超时)
* 如果写锁不可用,等待指定时间
*
* 超时处理:
* - 在指定时间内获取锁,返回true
* - 超时未获取到锁,返回false
* - 等待过程中可被中断
*
* @param timeout 等待时间
* @param unit 时间单位
* @return 如果获取成功返回true,否则返回false
* @throws InterruptedException 如果线程被中断
*/
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
/**
* 释放写锁
* 减少写锁计数,如果为0则完全释放写锁
*
* 释放过程:
* 1. 减少写锁计数
* 2. 如果计数为0,完全释放写锁
* 3. 唤醒等待队列中的线程
* 4. 允许其他线程获取读锁或写锁
*
* 异常处理:
* - 如果当前线程不是写锁的持有者,抛出IllegalMonitorStateException
*/
public void unlock() {
sync.release(1); // 调用AQS的独占锁释放方法
}
/**
* 创建新的Condition实例
* 写锁支持Condition,与ReentrantLock类似
*
* Condition特点:
* - 与特定的写锁实例绑定
* - 支持线程等待/通知机制
* - 更灵活的控制
*
* @return 新的Condition实例
*/
public Condition newCondition() {
return sync.newCondition();
}
/**
* 返回写锁的字符串表示
* @return 字符串表示
*/
public String toString() {
Thread o = sync.getOwner();
return super.toString() +
((o == null) ?
"[Unlocked]" :
"[Locked by thread " + o.getName() + "]");
}
}
4. 查询和状态方法(详细注释)
/**
* 判断是否持有写锁
* @return 如果持有写锁返回true,否则返回false
*
* 查询结果:
* - 如果任何线程持有写锁返回true
* - 如果没有线程持有写锁返回false
*
* 使用场景:
* - 监控锁的状态
* - 实现复杂的同步逻辑
* - 调试和诊断
*/
public boolean isWriteLocked() {
return sync.isWriteLocked();
}
/**
* 判断当前线程是否持有写锁
* @return 如果当前线程持有写锁返回true,否则返回false
*
* 查询结果:
* - 如果当前线程持有写锁返回true
* - 否则返回false
*
* 使用场景:
* - 检查锁的持有情况
* - 实现可重入逻辑
* - 避免重复获取锁
*/
public boolean isWriteLockedByCurrentThread() {
return sync.isWriteLockedByCurrentThread();
}
/**
* 获取写锁重入计数
* @return 重入计数
*
* 查询结果:
* - 如果当前线程持有写锁,返回重入次数
* - 如果当前线程未持有写锁,返回0
*
* 使用场景:
* - 调试和监控
* - 实现复杂的同步逻辑
* - 避免过度释放锁
*/
public int getWriteHoldCount() {
return sync.getWriteHoldCount();
}
/**
* 获取读锁持有计数
* @return 读锁持有计数
*
* 查询结果:
* - 返回当前持有的读锁总数
* - 包括所有线程持有的读锁
*
* 使用场景:
* - 监控读锁的使用情况
* - 实现负载监控
* - 性能调优
*/
public int getReadLockCount() {
return sync.getReadLockCount();
}
/**
* 获取指定线程的读锁持有计数
* @param thread 要查询的线程
* @return 读锁持有计数
*
* 查询结果:
* - 返回指定线程持有的读锁数量
* - 如果线程未持有读锁返回0
*
* 使用场景:
* - 调试和诊断
* - 实现复杂的同步逻辑
* - 分析线程状态
*/
public int getReadHoldCount(Thread thread) {
return sync.getReadHoldCount(thread);
}
/**
* 获取当前线程的读锁持有计数
* @return 读锁持有计数
*
* 查询结果:
* - 返回当前线程持有的读锁数量
* - 如果未持有读锁返回0
*
* 使用场景:
* - 检查锁的持有情况
* - 实现可重入逻辑
* - 避免重复获取锁
*/
public int getReadHoldCount() {
return sync.getReadHoldCount(Thread.currentThread());
}
/**
* 判断锁是否是公平锁
* @return 如果是公平锁返回true,否则返回false
*
* 查询结果:
* - 通过检查sync的类型来判断
* - FairSync类型表示公平锁
* - NonfairSync类型表示非公平锁
*/
public final boolean isFair() {
return sync instanceof FairSync;
}
/**
* 获取当前持有写锁的线程
* @return 持有写锁的线程,如果未被持有则返回null
*
* 查询结果:
* - 如果写锁被持有,返回持有线程
* - 如果写锁空闲,返回null
*
* 使用场景:
* - 调试和监控
* - 实现诊断工具
* - 分析死锁情况
*/
protected Thread getOwner() {
return sync.getOwner();
}
/**
* 查询是否有线程正在等待获取写锁
* @return 如果有等待线程返回true,否则返回false
*
* 查询结果:
* - 检查AQS的同步队列
* - 如果有等待写锁的线程返回true
* - 否则返回false
*
* 使用场景:
* - 监控锁的竞争情况
* - 实现负载均衡
* - 优化系统性能
*/
public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
/**
* 查询指定线程是否正在等待获取锁
* @param thread 要查询的线程
* @return 如果线程在等待队列中返回true,否则返回false
*
* 查询结果:
* - 如果指定线程在等待队列中返回true
* - 否则返回false
*
* 使用场景:
* - 调试和诊断
* - 实现复杂的同步逻辑
* - 分析线程状态
*/
public final boolean hasQueuedThread(Thread thread) {
return sync.isQueued(thread);
}
/**
* 获取等待获取锁的线程数量
* @return 等待线程数量
*
* 查询结果:
* - 返回等待队列中的线程数量
* - 这是一个估算值,因为线程状态可能随时变化
*
* 使用场景:
* - 监控锁的竞争程度
* - 实现负载监控
* - 性能调优
*/
public final int getQueueLength() {
return sync.getQueueLength();
}
/**
* 获取等待获取锁的线程集合
* @return 等待线程集合
*
* 查询结果:
* - 返回等待队列中线程的集合
* - 集合是线程安全的快照
*
* 使用场景:
* - 调试和诊断
* - 实现管理工具
* - 分析系统状态
*/
protected Collection<Thread> getQueuedThreads() {
return sync.getQueuedThreads();
}
5. ReentrantReadWriteLock 的特点分析
核心设计理念:
/**
* ReentrantReadWriteLock的核心设计思想:
*
* 1. 读写分离:
* - 读锁:共享锁,多个读线程可以同时持有
* - 写锁:独占锁,写线程独占访问
* - 读读不互斥,读写互斥,写写互斥
*
* 2. 状态管理:
* - 使用一个int字段管理两种锁的状态
* - 高16位表示读锁计数
* - 低16位表示写锁计数
* - 通过位运算高效管理状态
*
* 3. 可重入性:
* - 支持读锁和写锁的可重入
* - 每个线程维护自己的持有计数
* - 完全释放时才允许其他线程获取
*
* 4. 公平性选择:
* - 提供公平和非公平两种模式
* - 公平锁避免线程饥饿
* - 非公平锁提高性能
*
* 5. 线程本地存储:
* - 使用ThreadLocal跟踪每个线程的读锁持有情况
* - 避免竞争和同步开销
* - 优化单个读线程的场景
*
* 6. AQS集成:
* - 继承AbstractQueuedSynchronizer
* - 复用成熟的队列管理机制
* - 提供完整的同步框架
*
* 适用场景:
* - 读操作远多于写操作的场景
* - 需要高并发读取的场景
* - 需要比ReentrantLock更细粒度控制的场景
* - 需要Condition支持的写锁场景
*/
性能特征分析:
/**
* ReentrantReadWriteLock的性能特征:
*
* 获取锁时间复杂度:
* - 无竞争读锁:O(1) - 直接CAS操作
* - 无竞争写锁:O(1) - 直接CAS操作
* - 有竞争:O(1) 平均,O(n) 最坏(等待队列长度)
*
* 释放锁时间复杂度:
* - 读锁释放:O(1) - 更新状态并可能唤醒写锁
* - 写锁释放:O(1) - 更新状态并唤醒等待线程
*
* 内存复杂度:
* - O(1) 基本开销
* - O(n) 等待队列开销(n为等待线程数)
* - O(t) ThreadLocal开销(t为持有读锁的线程数)
*
* 并发特性:
* - 完全线程安全
* - 支持高并发读取
* - 读写互斥保证数据一致性
* - 无锁设计(通过CAS和AQS)
*
* 读写性能对比:
* - 读锁:多个线程可以并发获取
* - 写锁:独占访问,性能相对较低
* - 读多写少:性能优势明显
* - 写多读少:可能不如ReentrantLock
*
* 公平性对比:
* - 非公平锁:吞吐量更高,可能有线程饥饿
* - 公平锁:避免饥饿,吞吐量略低
*
* 与ReentrantLock对比:
* - 读写分离:更细粒度的控制
* - 读并发:支持多个读线程同时访问
* - 复杂度:实现更复杂,开销略大
* - 适用场景:读多写少的场景
*/
6. 使用示例和最佳实践
/**
* 使用示例:
*
* // 基本使用
* ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
* Lock readLock = rwLock.readLock();
* Lock writeLock = rwLock.writeLock();
*
* // 读操作
* readLock.lock();
* try {
* // 读取共享数据
* // 多个读线程可以同时执行
* } finally {
* readLock.unlock();
* }
*
* // 写操作
* writeLock.lock();
* try {
* // 修改共享数据
* // 独占访问,其他读写操作都会阻塞
* } finally {
* writeLock.unlock();
* }
*
* // 可中断的锁获取
* try {
* readLock.lockInterruptibly();
* try {
* // 读操作
* } finally {
* readLock.unlock();
* }
* } catch (InterruptedException e) {
* Thread.currentThread().interrupt();
* }
*
* // 带超时的锁获取
* try {
* if (writeLock.tryLock(5, TimeUnit.SECONDS)) {
* try {
* // 写操作
* } finally {
* writeLock.unlock();
* }
* } else {
* // 获取锁超时
* System.out.println("Failed to acquire write lock within timeout");
* }
* } catch (InterruptedException e) {
* Thread.currentThread().interrupt();
* }
*
* // 公平锁
* ReentrantReadWriteLock fairRwLock = new ReentrantReadWriteLock(true);
*
* // 使用Condition(仅写锁支持)
* Condition condition = writeLock.newCondition();
*
* // 等待条件
* writeLock.lock();
* try {
* while (!conditionMet()) {
* condition.await();
* }
* // 条件满足后的处理
* } finally {
* writeLock.unlock();
* }
*
* // 通知等待的线程
* writeLock.lock();
* try {
* // 改变条件
* setConditionMet(true);
* condition.signal(); // 或者 condition.signalAll();
* } finally {
* writeLock.unlock();
* }
*
* 最佳实践:
*
* 1. 正确的锁获取和释放:
* ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
* Lock readLock = rwLock.readLock();
* Lock writeLock = rwLock.writeLock();
*
* // 读操作
* readLock.lock();
* try {
* // 读取操作
* } finally {
* readLock.unlock(); // 必须在finally块中释放
* }
*
* // 写操作
* writeLock.lock();
* try {
* // 写入操作
* } finally {
* writeLock.unlock(); // 必须在finally块中释放
* }
*
* 2. 避免读写锁嵌套:
* // 错误的做法:可能导致死锁
* readLock.lock();
* try {
* // 一些操作
* if (needToUpdate()) {
* writeLock.lock(); // 危险!可能导致死锁
* try {
* // 更新操作
* } finally {
* writeLock.unlock();
* }
* }
* } finally {
* readLock.unlock();
* }
*
* // 正确的做法:统一使用写锁
* writeLock.lock();
* try {
* // 读取操作
* // 更新操作
* } finally {
* writeLock.unlock();
* }
*
* 3. 合理使用可重入性:
* private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
* private final Lock readLock = rwLock.readLock();
* private final Lock writeLock = rwLock.writeLock();
*
* public void outerReadMethod() {
* readLock.lock();
* try {
* innerReadMethod(); // 同一线程可以再次获取读锁
* } finally {
* readLock.unlock(); // 只需要一次unlock
* }
* }
*
* public void innerReadMethod() {
* readLock.lock();
* try {
* // 读取操作
* System.out.println("Read hold count: " + rwLock.getReadHoldCount());
* } finally {
* readLock.unlock();
* }
* }
*
* 4. 选择合适的公平性:
* // 读多写少且对公平性要求不高:非公平锁(默认)
* ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
*
* // 需要避免饥饿:公平锁
* ReentrantReadWriteLock fairRwLock = new ReentrantReadWriteLock(true);
*
* 5. 设置合理的超时时间:
* try {
* if (readLock.tryLock(10, TimeUnit.SECONDS)) {
* try {
* // 读操作
* } finally {
* readLock.unlock();
* }
* } else {
* // 超时处理
* System.out.println("Read operation timed out");
* }
* } catch (InterruptedException e) {
* Thread.currentThread().interrupt();
* }
*
* 6. 监控锁的使用情况:
* ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
*
* // 检查锁的状态
* if (rwLock.isWriteLocked()) {
* System.out.println("Write lock is currently held");
* }
*
* if (rwLock.isWriteLockedByCurrentThread()) {
* System.out.println("Current thread holds the write lock");
* System.out.println("Write hold count: " + rwLock.getWriteHoldCount());
* }
*
* System.out.println("Read lock count: " + rwLock.getReadLockCount());
* System.out.println("Current thread read hold count: " + rwLock.getReadHoldCount());
*
* // 检查等待队列
* if (rwLock.hasQueuedThreads()) {
* System.out.println("Threads waiting for lock: " + rwLock.getQueueLength());
* }
*
* 7. 使用Condition(仅写锁支持):
* private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
* private final Lock writeLock = rwLock.writeLock();
* private final Condition notFull = writeLock.newCondition();
* private final Condition notEmpty = writeLock.newCondition();
*
* // 生产者
* public void put(Object item) throws InterruptedException {
* writeLock.lock();
* try {
* while (isFull()) {
* notFull.await(); // 等待空间
* }
* // 添加元素
* notEmpty.signal(); // 通知消费者
* } finally {
* writeLock.unlock();
* }
* }
*
* // 消费者
* public Object take() throws InterruptedException {
* writeLock.lock();
* try {
* while (isEmpty()) {
* notEmpty.await(); // 等待元素
* }
* Object item = remove(); // 移除元素
* notFull.signal(); // 通知生产者
* return item;
* } finally {
* writeLock.unlock();
* }
* }
*
* 8. 避免长时间持有锁:
* // 错误的做法:长时间持有锁
* writeLock.lock();
* try {
* // 大量计算或I/O操作
* expensiveOperation(); // 不应该在锁内执行
* // 更新共享数据
* } finally {
* writeLock.unlock();
* }
*
* // 正确的做法:减少锁持有时间
* Object result = expensiveOperation(); // 在锁外执行
* writeLock.lock();
* try {
* // 只在必要时持有锁
* updateSharedData(result);
* } finally {
* writeLock.unlock();
* }
*
* 9. 处理异常:
* ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
* Lock readLock = rwLock.readLock();
*
* readLock.lock();
* try {
* // 可能抛出异常的代码
* riskyReadOperation();
* } catch (Exception e) {
* // 处理异常
* System.err.println("Read operation failed: " + e.getMessage());
* throw e; // 重新抛出或处理
* } finally {
* readLock.unlock(); // 确保锁被释放
* }
*
* 10. 性能调优:
* // 在高并发读场景下监控性能
* ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
*
* // 定期检查锁的使用情况
* if (rwLock.getReadLockCount() > 1000) {
* System.out.println("High read contention detected");
* // 可能需要优化数据结构或访问模式
* }
*
* if (rwLock.getQueueLength() > 100) {
* System.out.println("High lock contention detected");
* // 可能需要减少锁的粒度
* }
*/
7. 与其他同步机制的比较
/**
* ReentrantReadWriteLock vs ReentrantLock vs synchronized vs StampedLock:
*
* ReentrantReadWriteLock:
* - 读写分离,读读不互斥
* - 支持多个读线程并发访问
* - 写锁独占访问
* - 支持公平性和非公平性
* - 读锁不支持Condition
* - 写锁支持Condition
*
* ReentrantLock:
* - 独占锁,读写都互斥
* - 不区分读写操作
* - 支持公平性和非公平性
* - 支持Condition
* - 实现相对简单
*
* synchronized:
* - JVM内置锁
* - 自动释放锁
* - JVM优化(偏向锁、轻量级锁等)
* - 不支持读写分离
* - 不支持公平性选择
* - 不支持Condition(Object的wait/notify)
*
* StampedLock:
* - JDK 8新增
* - 更高性能的读写锁
* - 支持乐观读
* - 不支持重入
* - 不支持Condition
* - 更复杂的使用方式
*
* 选择建议:
* - 读多写少:ReentrantReadWriteLock
* - 简单同步需求:synchronized
* - 需要Condition:ReentrantLock
* - 高性能读操作:StampedLock
* - 复杂同步逻辑:ReentrantLock
*
* 性能对比:
* - 无竞争:synchronized ≈ ReentrantLock ≈ ReentrantReadWriteLock
* - 有竞争:ReentrantLock ≥ synchronized(JDK 1.6后)
* - 读多写少:ReentrantReadWriteLock > ReentrantLock > synchronized
* - 高并发读:StampedLock > ReentrantReadWriteLock
* - 写多读少:ReentrantLock ≥ ReentrantReadWriteLock
*/
8. 总结
ReentrantReadWriteLock 的核心特性:
-
读写分离:
- 读锁:共享锁,多个读线程可以同时持有
- 写锁:独占锁,写线程独占访问
- 读读不互斥,读写互斥,写写互斥
-
可重入性:
- 支持读锁和写锁的可重入
- 每个线程维护自己的持有计数
- 完全释放时才允许其他线程获取
-
灵活性:
- 支持可中断的锁获取
- 支持超时控制
- 提供公平和非公平两种模式
- 写锁支持Condition条件等待
-
高性能:
- 基于AQS实现,性能优秀
- 无竞争时使用CAS操作
- 有竞争时使用队列管理
- 读并发提高整体性能
-
丰富的API:
- 提供详细的锁状态查询
- 支持监控和诊断
- 便于调试和性能调优
-
线程安全:
- 所有操作都是线程安全的
- 支持高并发环境
- 无锁设计保证性能
适用场景:
- 读操作远多于写操作的场景
- 需要高并发读取的场景
- 需要比ReentrantLock更细粒度控制的场景
- 需要Condition支持的写锁场景
- 缓存系统、数据库访问等读多写少的应用
注意事项:
- 必须在finally块中释放锁
- 避免读写锁嵌套导致死锁
- 合理选择公平性策略
- 正确处理中断异常
- 监控锁的使用情况
- 避免长时间持有锁
- 注意读写锁的语义区别
性能优化建议:
- 根据读写比例选择合适的锁类型
- 合理设置超时时间
- 使用公平锁避免线程饥饿
- 监控锁的竞争情况
- 优化临界区代码减少持有时间
- 考虑使用更细粒度的锁
- 定期分析和调优锁的使用
- 在读多写少的场景下充分发挥读并发优势

166

被折叠的 条评论
为什么被折叠?



