ReentrantReadWriteLock即实现了AQS的独占模式(写锁),又实现了共享模式(读锁)
1.源码中关于这个类的说明的摘录。
它是利用ReentrantLock实现了ReadWriteLock接口。虽然他不会给所有的读锁和写锁的获取者一个顺序,但是它支持可选的公平策略。
默认的非公平策略:一个非公平锁可能会一直推迟读或者写的线程,但是他有比公平锁更高的吞吐量。
公平策略:释放当前锁时,为等待时间最长的write线程分配锁。如果有一组读的线程,比所有的写线程等待时间要长,那么这组读线程会获得锁。
重入:此锁允许 reader 和 writer 按照 ReentrantLock 的样式重新获取读取锁或写入锁。在写入线程保持的所有写入锁都已经释放后,才允许重入。此外,writer 可以获取读取锁,但反过来则不成立。在其他应用程序中,当在调用或回调那些在读取锁状态下执行读取操作的方法期间保持写入锁时,重入很有用。如果 reader 试图获取写入锁,那么将永远不会获得
此锁最多支持 65535 个递归写入锁和 65535 个读取锁。试图超出这些限制将导致锁方法抛出error。
2.Sync
ReetrantReadWriteLock内部主要有Sync,NonfairSync,FairSync,ReadLock,WriteLock。其中ReadLock和WriteLock都是内部组合了Sync来实现的,Sync继承了AQS类。
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 6317671515068378041L;
/*
* Read vs write count extraction constants and functions.
* Lock state is logically divided into two unsigned shorts:
* The lower one representing the exclusive (writer) lock hold count,
* and the upper the shared (reader) hold count.
*Lock的状态被分成进入了两个无符号短整形。较低的位数的那个表示独占锁的数量(写锁)
*高位的是表示共享锁的数量(读锁)
*/
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;
/** Returns the number of shared holds represented in count */
//返回共享状态下锁的数量,也就是把int C往无符号右移16位
static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
/** Returns the number of exclusive holds represented in count */
//返回独占状态下锁的数量,也就是int c和EXCLUSIVE_MASK做与操作。
static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
/**
* A counter for per-thread read hold counts.
* Maintained as a ThreadLocal; cached in cachedHoldCounter
*/
//一个计数器用于让每个线程读到获取锁的数量。用ThreadLocal来保存,
//缓存在一个叫cachedHoldCounter的变量中。
static final class HoldCounter {
int count = 0;
// Use id, not reference, to avoid garbage retention
//使用ID,而不是引用,是为了防止影响垃圾回收
final long tid = getThreadId(Thread.currentThread());
}
/**
* ThreadLocal subclass. Easiest to explicitly define for sake
* of deserialization mechanics.
*/
//ThreadLocal的子类,最容易明确的反序列化方式,
static final class ThreadLocalHoldCounter
extends ThreadLocal<HoldCounter> {
public HoldCounter initialValue() {
return new HoldCounter();
}
}
/**
* The number of reentrant read locks held by current thread.
* Initialized only in constructor and readObject.
* Removed whenever a thread's read hold count drops to 0.
*/
//表示当前线程或拥有的重入的读锁的数量。只在序列化readObject和构造函数中被初始化
//不论何时,当一个的读锁变成0的时候移除它
private transient ThreadLocalHoldCounter readHolds;
/**
* The hold count of the last thread to successfully acquire
* readLock. This saves ThreadLocal lookup in the common case
* where the next thread to release is the last one to
* acquire. This is non-volatile since it is just used
* as a heuristic, and would be great for threads to cache.
*最后一个成功获得读锁的线程持有的锁的计数,这样在下一个要释放的线程
*是最后一个试图获取锁的线程的情况下,比较节约ThreadLocal的寻找时间
*他没有被定义成voliate,因为他只是用于启发(??),这对于缓存比较合适
* <p>Can outlive the Thread for which it is caching the read
* hold count, but avoids garbage retention by not retaining a
* reference to the Thread.
*可以比保存这个缓存的线程活的更久,但是防止垃圾保留,所以没有使用线程的引用。
* <p>Accessed via a benign data race; relies on the memory
* model's final field and out-of-thin-air guarantees.
*/
//获取读锁的线程放入ThreadLocalHoldCounter,
//cachedHoldCounter放入的是最后一个获取锁的线程。
private transient HoldCounter cachedHoldCounter;
/**
* firstReader is the first thread to have acquired the read lock.
* firstReaderHoldCount is firstReader's hold count.
*firstReader是成功获取读锁的第一个线程。firstReaderHoldCount是线程的持有锁计数
* <p>More precisely, firstReader is the unique thread that last
* changed the shared count from 0 to 1, and has not released the
* read lock since then; null if there is no such thread.
*确切的锁,firstReader是最后一次将共享计数从0改成1的那唯一一个线程。
*并且自那以后还没有释放读锁,如果没有那样的线程则置为null
* <p>Cannot cause garbage retention unless the thread terminated
* without relinquishing its read locks, since tryReleaseShared
* sets it to null.
*除非线程在没有放弃读锁时终止,否则不会导致垃圾保留,因为tryRleaseShared
*会把他置为null。
* <p>Accessed via a benign data race; relies on the memory
* model's out-of-thin-air guarantees for references.
*
* <p>This allows tracking of read holds for uncontended read
* locks to be very cheap.
*/
private transient Thread firstReader = null;
private transient int firstReaderHoldCount;
Sync() {
readHolds = new ThreadLocalHoldCounter();
//确保readHolds的内存可见性,可能是利用state 的violatile性质。
setState(getState()); // ensures visibility of readHolds
}
/*
* Acquires and releases use the same code for fair and
* nonfair locks, but differ in whether/how they allow barging
* when queues are non-empty.
*对于公平锁还有非公平锁,获取锁和释放锁用的是相同的代码
*但是当队列是非空时候,在是否允许barging和怎么样barging这个问题上不同
*/
/**
* Returns true if the current thread, when trying to acquire
* the read lock, and otherwise eligible to do so, should block
* because of policy for overtaking other waiting threads.
*如果当前线程,正在试图获取读锁并且有资格这样做,返回true,
*因为超出其他等待线程的策略应该堵塞
*/
//根据其公平策略决定是否允许获取读锁
abstract boolean readerShouldBlock();
/**
* Returns true if the current thread, when trying to acquire
* the write lock, and otherwise eligible to do so, should block
* because of policy for overtaking other waiting threads.
*如果当前线程,正在试图获取写锁并且有资格这样做,返回true,
*因为超出其他等待线程的策略应该堵塞
*/
// 根据其公平策略决定是否允许获取写锁
abstract boolean writerShouldBlock();
/*
* Note that tryRelease and tryAcquire can be called by
* Conditions. So it is possible that their arguments contain
* both read and write holds that are all released during a
* condition wait and re-established in tryAcquire.
*tryRelease 和 tryAcquire可能被Conditions调用,所以可能他们的参数保留了
*在Condition wait期间或者重新tryAcquire期间已经被释放的读锁和写锁的计数
*/
protected final boolean tryRelease(int releases) {
if (!isHeldExclusively())//是否是当前线程持有锁,如果不是,就不能tryRelease()
throw new IllegalMonitorStateException();
int nextc = getState() - releases;//当前的state减去释放掉的锁的计数
boolean free = exclusiveCount(nextc) == 0;//检查独占锁是否等于0
if (free)//如果独占锁的状态为0,则证明释放了锁,把拥有独占的线程设置为null
setExclusiveOwnerThread(null);
setState(nextc);//重新设置state
return free;
}
protected final boolean tryAcquire(int acquires) {
/*
* Walkthrough:
* 1. If read count nonzero or write count nonzero
* and owner is a different thread, fail.
*如果读取计数非空,或者写锁计数非空,或者锁拥有者是另一个线程,失败
* 2. If count would saturate, fail. (This can only
* happen if count is already nonzero.)
*如果计数饱和(65535),失败(这只会在计数已经非空的情况下)
* 3. Otherwise, this thread is eligible for lock if
* it is either a reentrant acquire or
* queue policy allows it. If so, update state
* and set owner.
*其他情况下,如果是一个重入获取,或者队列的策略允许,这个线程有获取锁的资格
*如果获取了,更新state,设置锁拥有者
*/
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)
//因为state不为0,证明独占和共享至少一个不为0,如果w为0,
//就是目前有共享锁,则返回false。如果w不为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;
}
//进行到这里证明目前没有任何锁,先writerShouldBlock()查看写锁能进行,
//在尝试设置state来获取锁,
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires))
return false;
setExclusiveOwnerThread(current);
return true;
}
protected final boolean tryReleaseShared(int unused) {
Thread current = Thread.currentThread();
//如果当前线程就是第一个获取读锁的线程
//则线程持有的锁计数减一,如果本来就是1,则firstReader置null
if (firstReader == current) {
// assert firstReaderHoldCount > 0;
if (firstReaderHoldCount == 1)
firstReader = null;
else
firstReaderHoldCount--;
} else {
//将当前线程的readHolds的计数减一,
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;//state中共享锁的部分减一
if (compareAndSetState(c, nextc))
// Releasing the read lock has no effect on readers,
// but it may allow waiting writers to proceed if
// both read and write locks are now free.
//释放读锁对正在读的作业没有影响,但是如果读写锁都空闲的话,可能导致正在
//等待的写作业继续执行。
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) {
/*
* Walkthrough:
* 1. If write lock held by another thread, fail.
*如果别的线程获取了写锁,失败
* 2. Otherwise, this thread is eligible for
* lock wrt state, so ask if it should block
* because of queue policy. If not, try
* to grant by CASing state and updating count.
* Note that step does not check for reentrant
* acquires, which is postponed to full version
* to avoid having to check hold count in
* the more typical non-reentrant case.
*除此之外,这个线程能够锁住wrt的state,所以是否阻塞由队列的策略来决定。
*如果不阻塞,试图CAS的修改状态,更新计数。这个步骤并不检查重入获取锁,
*将这个步骤延迟到完整版本来避免在更加典型的重入情况,检查保存计数
* 3. If step 2 fails either because thread
* apparently not eligible or CAS fails or count
* saturated, chain to version with full retry loop.
*如果第二失败,表明可能是cas失败或者计数越界了,
*/
Thread current = Thread.currentThread();
int c = getState();
//如果state的独占部分不为0(证明有写锁),且写锁不是当前线程,则返回-1(失败)
//因为拥有写锁的线程也可以获取读锁,可以进行锁的降级。
if (exclusiveCount(c) != 0 &&
getExclusiveOwnerThread() != current)
return -1;
//获取state共享部分的值,根据其公平策略决定是否允许获取读锁。然后将读锁state加一
//如果之前读锁state为0,证明当前是第一个获取读锁的线程,将firstReader设置为当前线程
//如果读锁state不为0,但是firstReader是当前线程,则将firstReaderHoldCount++
//再其他状态,把cachedHoldCounter(最后一个修改读锁的线程)设置为当前线程。
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);
}
/**
* Full version of acquire for reads, that handles CAS misses
* and reentrant reads not dealt with in tryAcquireShared.
*完整版本的读锁获取,处理CAS失败或者其他在tryAcquireShared没有处理成功的情况
*/
final int fullTryAcquireShared(Thread current) {
/*
* This code is in part redundant with that in
* tryAcquireShared but is simpler overall by not
* complicating tryAcquireShared with interactions between
* retries and lazily reading hold counts.
*这段代码和tryAcquireShared是部分重复的,
*/
HoldCounter rh = null;
for (;;) {
int c = getState();
if (exclusiveCount(c) != 0) {
if (getExclusiveOwnerThread() != current)
return -1;
// else we hold the exclusive lock; blocking here
// would cause deadlock.如果有线程持有写锁,在这里阻塞会导致死锁。
} else if (readerShouldBlock()) {//如果公平策略决定线程应该阻塞,也就是不能获取锁
// Make sure we're not acquiring read lock reentrantly
//如果当前线程是firstReader不处理,否则,结束申请锁操作
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;
}
}
//readerShouldBlock()同意申请锁
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;
}
}
}
/**
* Performs tryLock for write, enabling barging in both modes.
* This is identical in effect to tryAcquire except for lack
* of calls to writerShouldBlock.
*为了写尝试获取锁,两种模式都与允许插队(barging in)
*和tryAcquire实际上一行,除了没有调用writerShouldBlock。
*/
final boolean tryWriteLock() {
Thread current = Thread.currentThread();
int c = getState();
if (c != 0) {
//如果有线程持有读锁(哪怕是自己),则返回false(C!=0且w==0,证明有线程持有读锁)
//如果有线程持有写锁,如果是自己尝试重入,如果不是自己,返回false
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;
}
/**
* Performs tryLock for read, enabling barging in both modes.
* This is identical in effect to tryAcquireShared except for
* lack of calls to readerShouldBlock.
*为了读尝试获取锁,两种模式都与允许插队(barging in)
*和tryAcquireShared实际上一行,除了没有调用readerShouldBlock。
*/
final boolean tryReadLock() {
Thread current = Thread.currentThread();
for (;;) {
int c = getState();
//如果有线程持有写锁,且持有线程不是自己,返回false
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是自己,
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) {//否则如果firstReader原来就是自己,把计数加一
firstReaderHoldCount++;
} else {
//更新cachedHoldCounter,
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() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
//我们不需要这样做检查来确定当前线程是不是锁持有者,如果我们是在readState
return getExclusiveOwnerThread() == Thread.currentThread();
}
// Methods relayed to outer class
final ConditionObject newCondition() {
return new ConditionObject();
}
final Thread getOwner() {
// Must read state before owner to ensure memory consistency
//必须在获取之前读取状态来保证内存一致性
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;
}
/**
* Reconstitutes the instance from a stream (that is, deserializes it).
*/
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(); }
}
3.非公平Sync
static final class NonfairSync extends Sync {
private static final long serialVersionUID = -8159625535654395037L;
//非公平锁获取写锁不需要阻塞,总是可以参与竞争
final boolean writerShouldBlock() {
return false; // writers can always barge
}
final boolean readerShouldBlock() {
/* As a heuristic to avoid indefinite writer starvation,
* block if the thread that momentarily appears to be head
* of queue, if one exists, is a waiting writer. This is
* only a probabilistic effect since a new reader will not
* block if there is a waiting writer behind other enabled
* readers that have not yet drained from the queue.
*作为一个避免写锁无限饥饿的启发式方法,如果即将成为队列head的线程(也就是除了head的第一个node)
*存在且是一个希望获取写锁的线程,那么就阻塞获取读锁的动作。
*这是一个概率效应,因为如果在队列中的等待读锁的node后面有希望获取写锁的node
*那么就不会阻塞它。(也就是锁如果现在是写锁正在执行,先有一个读锁请求,再来一个写锁请求
*第一个写锁释放后,读锁能获取锁,写锁不行,然后读锁不停的重入,写锁阻塞)
*/
//返回head节点的next节点是不是独占模式,AQS方法
return apparentlyFirstQueuedIsExclusive();
}
}
4.公平版本Sync
static final class FairSync extends Sync {
private static final long serialVersionUID = -2274990926593161451L;
//通过AQS方法判断是不是有等待锁更久的线程。有更久的就先阻塞
final boolean writerShouldBlock() {
return hasQueuedPredecessors();
}
final boolean readerShouldBlock() {
return hasQueuedPredecessors();
}
}
5.ReadLock
public static class ReadLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = -5992448646407690164L;
private final Sync sync;
/**
* Constructor for use by subclasses
*
* @param lock the outer lock object
* @throws NullPointerException if the lock is null
*/
protected ReadLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
/**
* Acquires the read lock.
*获取读锁
* <p>Acquires the read lock if the write lock is not held by
* another thread and returns immediately.
*如果写锁没有被其他线程获取,则获取读锁
* <p>If the write lock is held by another thread then
* the current thread becomes disabled for thread scheduling
* purposes and lies dormant until the read lock has been acquired.
*如果写锁被其他线程获取,则当前线程不可以被线程调度,并且处于休眠状态直到获取锁。
*/
//尝试获取读锁,获取失败的话,就入队等待
public void lock() {
sync.acquireShared(1);
}
/**
* Acquires the read lock unless the current thread is
* {@linkplain Thread#interrupt interrupted}.
*获取读锁除非当前线程被中断
* <p>Acquires the read lock if the write lock is not held
* by another thread and returns immediately.
*
* <p>If the write lock is held by another thread then the
* current thread becomes disabled for thread scheduling
* purposes and lies dormant until one of two things happens:
*
* <ul>
*
* <li>The read lock is acquired by the current thread; or
*
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread.
*
* </ul>
*
* <p>If the current thread:
*
* <ul>
*
* <li>has its interrupted status set on entry to this method; or
*
* <li>is {@linkplain Thread#interrupt interrupted} while
* acquiring the read lock,
*
* </ul>
*
* then {@link InterruptedException} is thrown and the current
* thread's interrupted status is cleared.
*
* <p>In this implementation, as this method is an explicit
* interruption point, preference is given to responding to
* the interrupt over normal or reentrant acquisition of the
* lock.
*
* @throws InterruptedException if the current thread is interrupted
*/
public void lockInterruptibly() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
/**
* Acquires the read lock only if the write lock is not held by
* another thread at the time of invocation.
*
* <p>Acquires the read lock if the write lock is not held by
* another thread and returns immediately with the value
* {@code true}. Even when this lock has been set to use a
* fair ordering policy, a call to {@code tryLock()}
* <em>will</em> immediately acquire the read lock if it is
* available, whether or not other threads are currently
* waiting for the read lock. This "barging" behavior
* can be useful in certain circumstances, even though it
* breaks fairness. If you want to honor the fairness setting
* for this lock, then use {@link #tryLock(long, TimeUnit)
* tryLock(0, TimeUnit.SECONDS) } which is almost equivalent
* (it also detects interruption).
*
* <p>If the write lock is held by another thread then
* this method will return immediately with the value
* {@code false}.
*
* @return {@code true} if the read lock was acquired
*/
//如果不能获取锁,就立刻返回
public boolean tryLock() {
return sync.tryReadLock();
}
/**
* Acquires the read lock if the write lock is not held by
* another thread within the given waiting time and the
* current thread has not been {@linkplain Thread#interrupt
* interrupted}.
*
* <p>Acquires the read lock if the write lock is not held by
* another thread and returns immediately with the value
* {@code true}. If this lock has been set to use a fair
* ordering policy then an available lock <em>will not</em> be
* acquired if any other threads are waiting for the
* lock. This is in contrast to the {@link #tryLock()}
* method. If you want a timed {@code tryLock} that does
* permit barging on a fair lock then combine the timed and
* un-timed forms together:
*
* <pre> {@code
* if (lock.tryLock() ||
* lock.tryLock(timeout, unit)) {
* ...
* }}</pre>
*
* <p>If the write lock is held by another thread then the
* current thread becomes disabled for thread scheduling
* purposes and lies dormant until one of three things happens:
*
* <ul>
*
* <li>The read lock is acquired by the current thread; or
*
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread; or
*
* <li>The specified waiting time elapses.
*
* </ul>
*
* <p>If the read lock is acquired then the value {@code true} is
* returned.
*
* <p>If the current thread:
*
* <ul>
*
* <li>has its interrupted status set on entry to this method; or
*
* <li>is {@linkplain Thread#interrupt interrupted} while
* acquiring the read lock,
*
* </ul> then {@link InterruptedException} is thrown and the
* current thread's interrupted status is cleared.
*
* <p>If the specified waiting time elapses then the value
* {@code false} is returned. If the time is less than or
* equal to zero, the method will not wait at all.
*
* <p>In this implementation, as this method is an explicit
* interruption point, preference is given to responding to
* the interrupt over normal or reentrant acquisition of the
* lock, and over reporting the elapse of the waiting time.
*
* @param timeout the time to wait for the read lock
* @param unit the time unit of the timeout argument
* @return {@code true} if the read lock was acquired
* @throws InterruptedException if the current thread is interrupted
* @throws NullPointerException if the time unit is null
*/
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
/**
* Attempts to release this lock.
*
* <p>If the number of readers is now zero then the lock
* is made available for write lock attempts.
*/
public void unlock() {
sync.releaseShared(1);
}
/**
* Throws {@code UnsupportedOperationException} because
* {@code ReadLocks} do not support conditions.
*
* @throws UnsupportedOperationException always
*/
//读锁是共享模式,不支持codititon
public Condition newCondition() {
throw new UnsupportedOperationException();
}
/**
* Returns a string identifying this lock, as well as its lock state.
* The state, in brackets, includes the String {@code "Read locks ="}
* followed by the number of held read locks.
*
* @return a string identifying this lock, as well as its lock state
*/
public String toString() {
int r = sync.getReadLockCount();
return super.toString() +
"[Read locks = " + r + "]";
}
}
6.写锁
public static class WriteLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = -4992448646407690164L;
private final Sync sync;
/**
* Constructor for use by subclasses
*
* @param lock the outer lock object
* @throws NullPointerException if the lock is null
*/
protected WriteLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
/**
* Acquires the write lock.
*
* <p>Acquires the write lock if neither the read nor write lock
* are held by another thread
* and returns immediately, setting the write lock hold count to
* one.
*
* <p>If the current thread already holds the write lock then the
* hold count is incremented by one and the method returns
* immediately.
*
* <p>If the lock is held by another thread then the current
* thread becomes disabled for thread scheduling purposes and
* lies dormant until the write lock has been acquired, at which
* time the write lock hold count is set to one.
*/
public void lock() {
sync.acquire(1);
}
/**
* Acquires the write lock unless the current thread is
* {@linkplain Thread#interrupt interrupted}.
*
* <p>Acquires the write lock if neither the read nor write lock
* are held by another thread
* and returns immediately, setting the write lock hold count to
* one.
*
* <p>If the current thread already holds this lock then the
* hold count is incremented by one and the method returns
* immediately.
*
* <p>If the lock is held by another thread then the current
* thread becomes disabled for thread scheduling purposes and
* lies dormant until one of two things happens:
*
* <ul>
*
* <li>The write lock is acquired by the current thread; or
*
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread.
*
* </ul>
*
* <p>If the write lock is acquired by the current thread then the
* lock hold count is set to one.
*
* <p>If the current thread:
*
* <ul>
*
* <li>has its interrupted status set on entry to this method;
* or
*
* <li>is {@linkplain Thread#interrupt interrupted} while
* acquiring the write lock,
*
* </ul>
*
* then {@link InterruptedException} is thrown and the current
* thread's interrupted status is cleared.
*
* <p>In this implementation, as this method is an explicit
* interruption point, preference is given to responding to
* the interrupt over normal or reentrant acquisition of the
* lock.
*
* @throws InterruptedException if the current thread is interrupted
*/
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
/**
* Acquires the write lock only if it is not held by another thread
* at the time of invocation.
*
* <p>Acquires the write lock if neither the read nor write lock
* are held by another thread
* and returns immediately with the value {@code true},
* setting the write lock hold count to one. Even when this lock has
* been set to use a fair ordering policy, a call to
* {@code tryLock()} <em>will</em> immediately acquire the
* lock if it is available, whether or not other threads are
* currently waiting for the write lock. This "barging"
* behavior can be useful in certain circumstances, even
* though it breaks fairness. If you want to honor the
* fairness setting for this lock, then use {@link
* #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
* which is almost equivalent (it also detects interruption).
*
* <p>If the current thread already holds this lock then the
* hold count is incremented by one and the method returns
* {@code true}.
*
* <p>If the lock is held by another thread then this method
* will return immediately with the value {@code false}.
*
* @return {@code true} if the lock was free and was acquired
* by the current thread, or the write lock was already held
* by the current thread; and {@code false} otherwise.
*/
public boolean tryLock( ) {
return sync.tryWriteLock();
}
/**
* Acquires the write lock if it is not held by another thread
* within the given waiting time and the current thread has
* not been {@linkplain Thread#interrupt interrupted}.
*
* <p>Acquires the write lock if neither the read nor write lock
* are held by another thread
* and returns immediately with the value {@code true},
* setting the write lock hold count to one. If this lock has been
* set to use a fair ordering policy then an available lock
* <em>will not</em> be acquired if any other threads are
* waiting for the write lock. This is in contrast to the {@link
* #tryLock()} method. If you want a timed {@code tryLock}
* that does permit barging on a fair lock then combine the
* timed and un-timed forms together:
*
* <pre> {@code
* if (lock.tryLock() ||
* lock.tryLock(timeout, unit)) {
* ...
* }}</pre>
*
* <p>If the current thread already holds this lock then the
* hold count is incremented by one and the method returns
* {@code true}.
*
* <p>If the lock is held by another thread then the current
* thread becomes disabled for thread scheduling purposes and
* lies dormant until one of three things happens:
*
* <ul>
*
* <li>The write lock is acquired by the current thread; or
*
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread; or
*
* <li>The specified waiting time elapses
*
* </ul>
*
* <p>If the write lock is acquired then the value {@code true} is
* returned and the write lock hold count is set to one.
*
* <p>If the current thread:
*
* <ul>
*
* <li>has its interrupted status set on entry to this method;
* or
*
* <li>is {@linkplain Thread#interrupt interrupted} while
* acquiring the write lock,
*
* </ul>
*
* then {@link InterruptedException} is thrown and the current
* thread's interrupted status is cleared.
*
* <p>If the specified waiting time elapses then the value
* {@code false} is returned. If the time is less than or
* equal to zero, the method will not wait at all.
*
* <p>In this implementation, as this method is an explicit
* interruption point, preference is given to responding to
* the interrupt over normal or reentrant acquisition of the
* lock, and over reporting the elapse of the waiting time.
*
* @param timeout the time to wait for the write lock
* @param unit the time unit of the timeout argument
*
* @return {@code true} if the lock was free and was acquired
* by the current thread, or the write lock was already held by the
* current thread; and {@code false} if the waiting time
* elapsed before the lock could be acquired.
*
* @throws InterruptedException if the current thread is interrupted
* @throws NullPointerException if the time unit is null
*/
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
/**
* Attempts to release this lock.
*
* <p>If the current thread is the holder of this lock then
* the hold count is decremented. If the hold count is now
* zero then the lock is released. If the current thread is
* not the holder of this lock then {@link
* IllegalMonitorStateException} is thrown.
*
* @throws IllegalMonitorStateException if the current thread does not
* hold this lock
*/
public void unlock() {
sync.release(1);
}
/**
* Returns a {@link Condition} instance for use with this
* {@link Lock} instance.
* <p>The returned {@link Condition} instance supports the same
* usages as do the {@link Object} monitor methods ({@link
* Object#wait() wait}, {@link Object#notify notify}, and {@link
* Object#notifyAll notifyAll}) when used with the built-in
* monitor lock.
*
* <ul>
*
* <li>If this write lock is not held when any {@link
* Condition} method is called then an {@link
* IllegalMonitorStateException} is thrown. (Read locks are
* held independently of write locks, so are not checked or
* affected. However it is essentially always an error to
* invoke a condition waiting method when the current thread
* has also acquired read locks, since other threads that
* could unblock it will not be able to acquire the write
* lock.)
*
* <li>When the condition {@linkplain Condition#await() waiting}
* methods are called the write lock is released and, before
* they return, the write lock is reacquired and the lock hold
* count restored to what it was when the method was called.
*
* <li>If a thread is {@linkplain Thread#interrupt interrupted} while
* waiting then the wait will terminate, an {@link
* InterruptedException} will be thrown, and the thread's
* interrupted status will be cleared.
*
* <li> Waiting threads are signalled in FIFO order.
*
* <li>The ordering of lock reacquisition for threads returning
* from waiting methods is the same as for threads initially
* acquiring the lock, which is in the default case not specified,
* but for <em>fair</em> locks favors those threads that have been
* waiting the longest.
*
* </ul>
*
* @return the Condition object
*/
public Condition newCondition() {
return sync.newCondition();
}
/**
* Returns a string identifying this lock, as well as its lock
* state. The state, in brackets includes either the String
* {@code "Unlocked"} or the String {@code "Locked by"}
* followed by the {@linkplain Thread#getName name} of the owning thread.
*
* @return a string identifying this lock, as well as its lock state
*/
public String toString() {
Thread o = sync.getOwner();
return super.toString() + ((o == null) ?
"[Unlocked]" :
"[Locked by thread " + o.getName() + "]");
}
/**
* Queries if this write lock is held by the current thread.
* Identical in effect to {@link
* ReentrantReadWriteLock#isWriteLockedByCurrentThread}.
*
* @return {@code true} if the current thread holds this lock and
* {@code false} otherwise
* @since 1.6
*/
public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
}
/**
* Queries the number of holds on this write lock by the current
* thread. A thread has a hold on a lock for each lock action
* that is not matched by an unlock action. Identical in effect
* to {@link ReentrantReadWriteLock#getWriteHoldCount}.
*
* @return the number of holds on this lock by the current thread,
* or zero if this lock is not held by the current thread
* @since 1.6
*/
public int getHoldCount() {
return sync.getWriteHoldCount();
}
}