在上一节中,描述了Lock包的核心基础–AQS,本节将讲述其具体实现:ReentrantLock,ReentrantReadWriteLock。在这之前先说一下必要定义。
可重入锁:已在syn章节提及过,此处详细描述。某个线程获取到锁之后,在未释放锁之前的时间内,当需要获取锁时不需要获取锁的操作,可直接拿到资源。
公平锁:通俗的说,就是先等待的线程先获得锁。
非公平锁:与公平锁相反,每次需要获取锁时大家一起竞争,并不是先到先得。锁。
一、ReentrantLock
ReentrantLock是可重入锁,独占锁,实现Lock接口,内部实现了公平锁与非公平锁两种锁形式,默认使用非公平锁。
一、属性
private final Sync sync;
该类有属性Sync,用final修饰即初始化之后不可更改,Sync是AQS的一个子类,有两个子类NonfairSync与FairSync,分别用于实现非公平锁与公平锁。
二、静态内部类
接下来是静态内部类,这里使用静态内部类便是为了让这些类中的方法都只让ReentrantLock使用。
1.Sync
该类是AQS的子类,重写了一些方法(AQS需要实现,公平锁与非公平锁通用),是NonfairSync与FairSync的父类。
接下如acquire(),tryAcquire(),release()等属于AQS类的重要方法,在上一篇描述AQS的blog中已经详细阐述,此处不再阐述。
abstract static class Sync extends AbstractQueuedSynchronizer {
abstract void lock();
//不公平获取锁
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
} else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
//尝试释放锁
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
//是否拥有当前锁
protected final boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
//获取一个条件队列
final ConditionObject newCondition() {
return new ConditionObject();
}
//获取占有锁的线程
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
//获取该线程占有多少资源
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
//资源是否被抢占
final boolean isLocked() {
return getState() != 0;
}
}
上述代码实现都比较简单,根据注释就能了解,不再分析。
2.NonfairSync
该类是Sync的实现类,是不公平锁的实现。在ReentrantLock中使用的
static final class NonfairSync extends Sync {
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
上述代码有两方法:
lock():获取独占锁,若未获取则将线程阻塞等待。实现较简单:使用CAS将state从0置为1,若成功则代表获取资源成功;若失败则调用acquire()进行操作。
tryAcquire():获取锁,此处是直接调用父类Sync的nonfairTryAcquire方法。
疑问:nonfairTryAcquire()方法是不公平的获取锁,为什么要置于父类中,而不是子类NonfairSync中?
解答:通过跟踪源码,发现nonfairTryAcquire方法除了此处还有一处调用,在ReentrantLock对外提供的tryLock()方法中,用于立刻获取独占锁。故若将该方法放入子类NonfairSync中,则公平锁无法提供此功能。而对于我们来说,即使我们实现的是公平锁,在某些时刻也需要此功能。
3.FairSync
该类是Sync的实现类,是公平锁的实现。在ReentrantLock中使用的
static final class FairSync extends Sync {
final void lock() {
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
上述代码有两方法:
lock():获取独占锁,直接调用acquire()进行操作。
tryAcquire():获取锁。
4.总结
通过上述公平锁与非公平锁的实现,其区别在于:
- lock():获取独占锁,公平锁时直接调用acquire(1),将该线程放入队尾,等待获取;而非公平锁则是先直接获取锁(无论CLH队列中是否有其他线程在等待),失败才会将该线程放入队尾。
- tryAcquire():尝试获取锁,其实此方法只是获取锁过程中的一部分。其区别在于可以获取锁时,公平锁的处理是
!hasQueuedPredecessors() &&compareAndSetState(0, acquires)
,需要在队列前面没有其他等待线程才会尝试获取锁;而非公平锁的处理是compareAndSetState(0, acquires)
,无论是否有其他线程,直接尝试获取锁。
三、构造器
ReentrantLock对外提供两个构造器:
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
- ReentrantLock(),默认构造器,默认使用非公平锁,故上文中描述该类默认使用非公平锁
- ReentrantLock(boolean fair),带参构造器,传入true则是公平锁,false是非公平锁
四、对外提供方法
ReentrantLock提供了一系列方法,都是基于AQS以及上述Sync系列静态内部类实现,实现原理较简单,作用见注释,不一一详述。
//获取锁,若未获取则将线程阻塞等待
public void lock() {
sync.lock();
}
//获取锁。若未获取则将线程阻塞等待,直到获取锁。如果有中断请求就会产生中断异常
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
//立刻尝试获取锁
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
//立刻尝试在指定时间内获取锁,直接调用AQS中方法
public boolean tryLock(long timeout, TimeUnit unit)throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
//释放锁
public void unlock() {
sync.release(1);
}
//获取新的等待队列
public Condition newCondition() {
return sync.newCondition();
}
//获取当先线程占有资源数
public int getHoldCount() {
return sync.getHoldCount();
}
//是否是当前线程占有锁
public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
}
//锁是否被持有
public boolean isLocked() {
return sync.isLocked();
}
//是否是公平锁
public final boolean isFair() {
return sync instanceof FairSync;
}
//获取持有锁的线程
protected Thread getOwner() {
return sync.getOwner();
}
//是否有线程等待获取锁
public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
//CLH队列长度
public final int getQueueLength() {
return sync.getQueueLength();
}
//获取所有正在等待获取锁的线程,返回是list<Thread>
protected Collection<Thread> getQueuedThreads() {
return sync.getQueuedThreads();
}
//等待队列中是否有等待线程
public boolean hasWaiters(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
}
//等待队列中的线程数
public int getWaitQueueLength(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
}
//获取所有等待队列中的线程,返回是list<Thread>
protected Collection<Thread> getWaitingThreads(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
}
一、ReentrantReadWriteLock
ReentrantReadWriteLock是可重入锁。里面有两把锁,读锁与写锁,其中读锁采用共享锁,写锁采用独占锁。不能同时存在读锁与写锁。内部实现了公平锁与非公平锁两种锁形式,默认使用非公平锁。
写线程虽然一次只有一个访问数据,但读线程可以同时读取,而在实际中,读取往往都是大量的,写入是偶尔的,读-写锁利用了这一点。从理论上讲,与互斥锁相比,使用读-写锁所允许的并发性增强将带来更大的性能提高。在实践中,只有在多处理器上并且只在访问模式适用于共享数据时,才能完全实现并发性增强。
读写锁不能同时存在。
一、属性
private final ReentrantReadWriteLock.ReadLock readerLock;
private final ReentrantReadWriteLock.WriteLock writerLock;
final Sync sync;
该类有属性Sync,readerLock,writerLock,均用final修饰即初始化之后不可更改,Sync是AQS的一个子类,有两个子类NonfairSync与FairSync,分别用于实现非公平锁与公平锁。readerLock为读锁,writerLock为写锁
二、静态内部类
接下来是静态内部类,这里使用静态内部类便是为了让这些类中的方法都只让ReentrantLock使用。
1.Sync
该类是AQS的子类,重写了一些方法(AQS需要实现,公平锁与非公平锁通用),是NonfairSync与FairSync的父类。
接下如acquire(),tryAcquire(),release()等属于AQS类的重要方法,在上一篇描述AQS的blog中已经详细阐述,此处不再阐述。
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 6317671515068378041L;
/*
* 锁状态state是int型,读写分为两部分,各用一个无符号short来表示
* 低位的表示写锁即独享锁,高位的表示读锁共享数
*/
// 这个16是两个字节,一个short的长度
static final int SHARED_SHIFT = 16;
// 1左移16位,为00000000 00000001 00000000 00000000
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
// 1左移16位,减1,为65535,读写的获取锁的最大次数
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
// 右移16位,获取c高位的16位,表示读锁的共享总数(高位2字节全0)
static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
// 和两个字节的全1字节与操作,高位2字节全0,获取写锁的总数
static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
// 每个线程的计数器,保存读锁共享数
static final class HoldCounter {
int count = 0;
final long tid = getThreadId(Thread.currentThread());
}
// ThreadLocal的子类
static final class ThreadLocalHoldCounter
extends ThreadLocal<HoldCounter> {
// 初始化方法,返回HoldCounter
public HoldCounter initialValue() {
return new HoldCounter();
}
}
// 读线程的一个集合,但不包括最后一个读线程和第一个读线程
private transient ThreadLocalHoldCounter readHolds;
// 最后一个读线程的计数
private transient HoldCounter cachedHoldCounter;
// 第一个读线程
private transient Thread firstReader = null;
// 第一个读线程的计数
private transient int firstReaderHoldCount;
Sync() {
readHolds = new ThreadLocalHoldCounter();
setState(getState()); // ensures visibility of readHolds
}
// 读锁的阻塞
abstract boolean readerShouldBlock();
// 写锁的阻塞
abstract boolean writerShouldBlock();
// 释放写锁
protected final boolean tryRelease(int releases) {
if (!isHeldExclusively())
// 当前线程不是owner线程,不能进行释放
throw new IllegalMonitorStateException();
// 计算释放后的状态值
int nextc = getState() - releases;
// 如果当前写锁释放后,看是否还有写锁,没有写锁返回true
boolean free = exclusiveCount(nextc) == 0;
if (free)
// 没有写锁了将锁对象的当前owner置为null
setExclusiveOwnerThread(null);
// 更新state的新值
setState(nextc);
return free;
}
// 尝试获取写锁
protected final boolean tryAcquire(int acquires) {
// 当前线程
Thread current = Thread.currentThread();
// 状态c,包含读锁和写锁的总数
int c = getState();
// w表示写锁的总数
int w = exclusiveCount(c);
if (c != 0) {
// 如果写锁为0,说明当前有读锁(也可能是当前线程有读锁),不能获取写锁
// 如果写锁不为0,但是当前线程不是owner线程不可重入,不能获取写锁
if (w == 0 || current != getExclusiveOwnerThread())
return false;
// 写锁数量超过了65535报错
if (w + exclusiveCount(acquires) > MAX_COUNT)
throw new Error("Maximum lock count exceeded");
// 这里已经说明写锁是当前线程可重入的了,直接设置state值,返回true
setState(c + acquires);
return true;
}
// c==0时,如果写需要阻塞或者设置状态失败,返回false
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires))
return false;
// 设置锁的owner独占标识
setExclusiveOwnerThread(current);
return true;
}
// 尝试释放读锁
protected final boolean tryReleaseShared(int unused) {
// 当前线程current
Thread current = Thread.currentThread();
// 如果当前线程是第一个获取读锁的
if (firstReader == current) {
// 当前线程读锁总数为1,直接将firstReader置为null
if (firstReaderHoldCount == 1)
firstReader = null;
// 如果不为1,那么减掉1即可
else
firstReaderHoldCount--;
} else {
// 最后一个获取读锁的线程
HoldCounter rh = cachedHoldCounter;
// 如果当前线程也不是最后一个获取读锁的线程,从ThreadLocal中取
if (rh == null || rh.tid != getThreadId(current))
rh = readHolds.get();
// 当前线程读锁的个数
int count = rh.count;
// 如果count==1,释放了就为0,直接在ThreadLocal中去掉当前线程
if (count <= 1) {
readHolds.remove();
// count<=0,此时抛出不匹配释放锁的异常
if (count <= 0)
throw unmatchedUnlockException();
}
// 正常情况下,将当前线程的读锁count值减1即可。
--rh.count;
}
for (;;) {
int c = getState();
// 高位减1,新的读写锁值
int nextc = c - SHARED_UNIT;
// 尝试设置state值,预测之前为c,更新为nextc
if (compareAndSetState(c, nextc))
// 释放读锁不会影响其他读锁,但是如果这时读写锁都空闲,等待中的写线程将开始执行
// 这里只有读写锁都释放了,才返回true
return nextc == 0;
}
}
// 释放读锁的不匹配异常
private IllegalMonitorStateException unmatchedUnlockException() {
return new IllegalMonitorStateException(
"attempt to unlock read lock, not locked by current thread");
}
// 尝试获取读锁
protected final int tryAcquireShared(int unused) {
// 当前线程
Thread current = Thread.currentThread();
// 锁的state值
int c = getState();
// 如果有独占标识同时当前线程并不是独占线程时,直接返回-1
if (exclusiveCount(c) != 0 &&
getExclusiveOwnerThread() != current)
return -1;
// 读锁的总数
int r = sharedCount(c);
// 如果读不需要阻塞,同时读锁小于65535,并且能够CAS设置c的值读个数加1
// 这里的阻塞策略readerShouldBlock进行了判断,有两种情况:
// 1.公平模式:如果AQS队列前面有等待的结点,当前线程应该阻塞
// 2.非公平模式:如果AQS前面有线程在等待写锁,当前线程应该阻塞(这样做的原因是为了防止写饥饿)。
// 出现这个阻塞情况,就不走下边的if了,直接到最后走fullTryAcquireShared方法处理
if (!readerShouldBlock() &&
r < MAX_COUNT &&
compareAndSetState(c, c + SHARED_UNIT)) {
// 读锁个数为0,将当前线程作为第一个读线程单独保存,不存在ThreadLocal中
if (r == 0) {
firstReader = current;
// 当前线程即第一个读线程的读锁总数置为1
firstReaderHoldCount = 1;
// 如果r!=0,说明有读线程了,判断当前线程是不是第一个读线程
} else if (firstReader == current) {
// 如果当前线程就是第一个读线程,数量count加1即可
firstReaderHoldCount++;
} else {
// 当前线程不是第一个读线程,判断是不是最后一个读线程
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
// 当前线程不是最后一个读线程,从ThreadLocal中取线程
// 同时将最后一个读线程更新为当前线程
cachedHoldCounter = rh = readHolds.get();
// 这里如果当前线程就是最后一个读线程的话,如果count为0
else if (rh.count == 0)
// 需要重新set当前线程(之前释放时,readHolds.remove()进行过这个操作)
readHolds.set(rh);
// 将当前线程的count加1
rh.count++;
}
// 返回值1说明获取读锁成功了
return 1;
}
// 读线程阻塞时,执行这个方法
return fullTryAcquireShared(current);
}
// 该方法处理读线程阻塞的情况
final int fullTryAcquireShared(Thread current) {
HoldCounter rh = null;
for (;;) {
int c = getState();
// 独占标记存在且当前owner不是当前线程,不能重入
if (exclusiveCount(c) != 0) {
if (getExclusiveOwnerThread() != current)
return -1;
// 没有写锁存在时,如果读阻塞
// 这里的阻塞策略,如果:1.公平模式:如果当前AQS队列前面有等待的结点,返回false;2.非公平模式:如果
// AQS前面有线程在等待写锁,返回false(这样做的原因是为了防止写饥饿)。
} else if (readerShouldBlock()) {
// 如果当前线程是第一个读线程
if (firstReader == current) {
} else {
if (rh == null) {
// 优先赋值成上一次获取读锁成功的cache,即最后一个读锁
rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current)) {
// 如果和当前线程不匹配,从ThreadLocal中取
rh = readHolds.get();
if (rh.count == 0)
readHolds.remove();
}
}
// 不是读锁重入的情况,返回-1
if (rh.count == 0)
return -1;
}
}
// 如果读锁总数为65535,报错
if (sharedCount(c) == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
// 如果CAS将c的读锁总数增加1成功
if (compareAndSetState(c, c + SHARED_UNIT)) {
// 如果读锁数量为0,当前线程作为第一个线程存起来
if (sharedCount(c) == 0) {
firstReader = current;
firstReaderHoldCount = 1;
// 当前线程为第一个获取读锁的线程,数量加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;
}
}
}
// 和tryAcquire基本一致,去掉了考虑阻塞部分,相当于非公平模式的获取写锁
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;
}
// 和tryAcquireShared函数基本一致,去掉了考虑阻塞部分,相当于非公平模式的获取读锁
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;
}
}
}
protected final boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
final ConditionObject newCondition() {
return new ConditionObject();
}
final Thread getOwner() {
return ((exclusiveCount(getState()) == 0) ?
null :
getExclusiveOwnerThread());
}
final int getReadLockCount() {
return sharedCount(getState());
}
final boolean isWriteLocked() {
return exclusiveCount(getState()) != 0;
}
final int getWriteHoldCount() {
return isHeldExclusively() ? exclusiveCount(getState()) : 0;
}
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 void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
readHolds = new ThreadLocalHoldCounter();
setState(0); // reset to unlocked state
}
final int getCount() { return getState(); }
}
此静态内部类是ReentrantReadWriteLock的关键所在,过程已经在注释中详细描述,在此说明设计核心思想:
如何表示多个读锁与单个写锁 :由于state字段是32位的int,在次将state一分为2,用高16位记录读锁(共享锁)的状态,低16位保存写锁(独占锁)的状态,因此锁的数量上限都是65535
如何表示每个读锁、写锁的重入次数:可以把线程重入读锁的次数作为值存在 ThreadLocal 中
2.NonfairSync与FairSync
static final class NonfairSync extends Sync {
final boolean writerShouldBlock() {
return false; // writers can always barge
}
final boolean readerShouldBlock() {
return apparentlyFirstQueuedIsExclusive();
}
}
static final class FairSync extends Sync {
final boolean writerShouldBlock() {
return hasQueuedPredecessors();
}
final boolean readerShouldBlock() {
return hasQueuedPredecessors();
}
}
此处将公平锁与非公平锁放在一处,因为大多数逻辑已经在它们的父类Sync中实现,此处各只有两个方法:
- writerShouldBlock :写锁是阻塞进入等待队列(true)还是直接获取锁(false)。在非公平锁中,直接返回false;公平锁中,若无等待线程则返回false,有等待线程返回true
- readerShouldBlock:读锁是阻塞进入等待队列(true)还是直接获取锁(false)。在非公平锁中,如果队列的head.next正在等待独占锁(写锁),则返回true,否则返回false;公平锁中,若无等待线程则返回false,有等待线程返回true
3.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 {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
public void unlock() {
sync.releaseShared(1);
}
public Condition newCondition() {
throw new UnsupportedOperationException();
}
}
内部有一属性为sync,是从外部类继承过来,使用同一syn。使用共享锁,至于方法与ReentrantLock类似,同名方法作用一样,实现都是调用AQS以及Syn及子类方法,再次不赘述。
唯一需要注意的是,condition队列只支持独占锁,故此处不支持condition相关操作,直接抛出异常。
4.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 {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
//释放锁
public void unlock() {
sync.release(1);
}
//获取等待队列
public Condition newCondition() {
return sync.newCondition();
}
//获取写锁的个数
public int getHoldCount() {
return sync.getWriteHoldCount();
}
}
内部有一属性为sync,是从外部类继承过来,使用同一syn。使用独占锁,至于方法与ReentrantLock类似,同名方法作用一样,实现都是调用AQS以及Syn及子类方法,再次不赘述。
三、构造器
ReentrantReadWriteLock对外提供两个构造器:
public ReentrantReadWriteLock() {
this(false);
}
public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
protected ReadLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
protected WriteLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; }
- ReentrantReadWriteLock(),默认构造器,默认使用非公平锁,故上文中描述该类默认使用非公平锁
- ReentrantReadWriteLock(boolean fair),带参构造器,传入true则是公平锁,false是非公平锁
四、对外提供方法
ReentrantReadWriteLock提供了一系列方法,都是基于AQS以及上述Sync系列静态内部类实现,实现原理较简单,作用见注释,不一一详述。
// 返回当前拥有写入锁的线程,如果没有这样的线程,则返回 null。
protected Thread getOwner()
// 返回一个 collection,它包含可能正在等待获取读取锁的线程。
protected Collection<Thread> getQueuedReaderThreads()
// 返回一个 collection,它包含可能正在等待获取读取或写入锁的线程。
protected Collection<Thread> getQueuedThreads()
// 返回一个 collection,它包含可能正在等待获取写入锁的线程。
protected Collection<Thread> getQueuedWriterThreads()
// 返回等待获取读取或写入锁的线程估计数目。
int getQueueLength()
// 查询当前线程在此锁上保持的重入读取锁数量。
int getReadHoldCount()
// 查询为此锁保持的读取锁数量。
int getReadLockCount()
// 返回一个 collection,它包含可能正在等待与写入锁相关的给定条件的那些线程。
protected Collection<Thread> getWaitingThreads(Condition condition)
// 返回正等待与写入锁相关的给定条件的线程估计数目。
int getWaitQueueLength(Condition condition)
// 查询当前线程在此锁上保持的重入写入锁数量。
int getWriteHoldCount()
// 查询是否给定线程正在等待获取读取或写入锁。
boolean hasQueuedThread(Thread thread)
// 查询是否所有的线程正在等待获取读取或写入锁。
boolean hasQueuedThreads()
// 查询是否有些线程正在等待与写入锁有关的给定条件。
boolean hasWaiters(Condition condition)
// 如果此锁将公平性设置为 ture,则返回 true。
boolean isFair()
// 查询是否某个线程保持了写入锁。
boolean isWriteLocked()
// 查询当前线程是否保持了写入锁。
boolean isWriteLockedByCurrentThread()
// 返回用于读取操作的锁。
ReentrantReadWriteLock.ReadLock readLock()
// 返回用于写入操作的锁。
ReentrantReadWriteLock.WriteLock writeLock()