1.使用场景
ReentrantReadWriteLocks可用于提高某些集合的并发性。
仅当集合预计很大时,读线程比写线程多,并且需要用
超过同步开销的开销时,使用ReentrantReadWriteLocks通常是值得的。
2.锁降级
获取写锁,然后获取读锁,然后释放
写锁。但是,从读锁升级到写锁
不可能。
3.递归调用注意事项
此锁最多支持65535个递归写锁
和65535读锁。试图超过这些限制会从锁方法抛出
{@link Error}异常。
4.{@link Condition}支持
写锁提供了一个跟{@link Condition}同样功能的实现,针对写锁,
{@link ReentrantLock}的{@link Condition}被
{@link ReentrantLock#newCondition}提供
当然,{@link Condition}只能和写锁一起使用
读锁不支持{@link Condition}
5.序列化
该类的序列化行为与内置的锁方式相同
:反序列化的锁处于解锁状态,无论
序列化时锁的状态是什么。
6.中断
读锁和写锁在被获取期间,都容许中断
7.支持公平策略和非公平策略,并且可重入
package com.demo.lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* An implementation of {@link ReadWriteLock} supporting similar
* semantics to {@link ReentrantLock}.
* {@link ReadWriteLock}的实现与{@link ReentrantLock}很相似
* <p>This class has the following properties:
* 这个类有以下属性
* <ul>
* <li><b>Acquisition order</b>
* 公平锁和非公平锁
*
* <p>This class does not impose a reader or writer preference
* ordering for lock access. However, it does support an optional
* <em>fairness</em> policy.
*
* 这个类不增强读线程或写线程访问锁的顺序。可是,它提供了一个公平性的策略。
*
* <dl>
* <dt><b><i>Non-fair mode (default)</i></b>
* 默认采用非公平模式
* <dd>When constructed as non-fair (the default), the order of entry
* to the read and write lock is unspecified, subject to reentrancy
* constraints. A nonfair lock that is continuously contended may
* indefinitely postpone one or more reader or writer threads, but
* will normally have higher throughput than a fair lock.
*
* 当类使用非公平(默认)模式构建时,
* 未指定读写锁的进入顺序和对象重入
* 的约束。持续竞争的非公平锁可能
* 无限期推迟一个或多个读线程或写线程获得锁,但是
* 通常具有比公平锁更高的吞吐量。
*
* <dt><b><i>Fair mode</i></b>
* 公平模式
* <dd>When constructed as fair, threads contend for entry using an
* approximately arrival-order policy. When the currently held lock
* is released, either the longest-waiting single writer thread will
* be assigned the write lock, or if there is a group of reader threads
* waiting longer than all waiting writer threads, that group will be
* assigned the read lock.
*
* 当类使用公平模式构建时,线程采用先到先获得锁的策略。
* 当当前持有的锁
* 被释放,等待时间最长的单个写线程将
* 被分配写锁,或者如果有一组读线程
* 等待时间比所有等待的写线程长,则该组将
* 分配了读锁。
*
* <p>A thread that tries to acquire a fair read lock (non-reentrantly)
* will block if either the write lock is held, or there is a waiting
* writer thread. The thread will not acquire the read lock until
* after the oldest currently waiting writer thread has acquired and
* released the write lock. Of course, if a waiting writer abandons
* its wait, leaving one or more reader threads as the longest waiters
* in the queue with the write lock free, then those readers will be
* assigned the read lock.
*
* 如果写锁被持有,或者存在等待的写线程,试图获取公平读取锁(不可重入)的单个线程
* 将被阻塞。线程不会获得读锁,直到
* 在当前等待的最长写线程已经获得并且
* 释放写锁定之后,线程才会获得读锁。
* 当然,如果一个等待的写线程放弃了
* 等待,留下一个或多个读线程作为最长的等待者
* 在没有写锁的队列中,这些读线程将
* 分配了读锁。
*
* <p>A thread that tries to acquire a fair write lock (non-reentrantly)
* will block unless both the read lock and write lock are free (which
* implies there are no waiting threads). (Note that the non-blocking
* {@link ReentrantReadWriteLock.ReadLock#tryLock()} and {@link ReentrantReadWriteLock.WriteLock#tryLock()} methods
* do not honor this fair setting and will immediately acquire the lock
* if it is possible, regardless of waiting threads.)
* <p>
* </dl>
*
* 试图获得公平写锁(不可重入)的线程
* 除非读锁和写锁都是空闲的(这
* 意味着没有等待的线程)。
* (注意,非阻塞
* {@link ReentrantReadWriteLock.ReadLock#tryLock()}和{ @link ReentrantReadWriteLock.WriteLock#tryLock()}方法
* 不尊重这个公平的设置,
* 如果可能将立即获得锁,不考虑等待的线程。)
*
* <li><b>Reentrancy</b>
* 锁是否可重入
*
* <p>This lock allows both readers and writers to reacquire read or
* write locks in the style of a {@link ReentrantLock}. Non-reentrant
* readers are not allowed until all write locks held by the writing
* thread have been released.
*
* 该锁允许读线程和写线程重新获取读锁或
* 以{@link ReentrantLock}的样式获取写锁。
* 直到所有的写线程释放锁之后,非重入的读线程才被容许获得读锁。
*
*
* <p>Additionally, a writer can acquire the read lock, but not
* vice-versa. Among other applications, reentrancy can be useful
* when write locks are held during calls or callbacks to methods that
* perform reads under read locks. If a reader tries to acquire the
* write lock it will never succeed.
*
* 此外,写入者可以获得读锁,但不能
* 反之亦然。在其他应用中,当写锁被持有,调用或者回调方法期间,在读锁下执行读操作,
* 可重入可能很有用。
* 如果读线程试图获取
* 写锁定永远不会成功。
*
* <li><b>Lock downgrading</b>
* 锁降级
* <p>Reentrancy also allows downgrading from the write lock to a read lock,
* by acquiring the write lock, then the read lock and then releasing the
* write lock. However, upgrading from a read lock to the write lock is
* <b>not</b> possible.
*
* 可重入性还允许从写锁降级到读锁,
* 获取写锁,然后获取读锁,然后释放
* 写锁。但是,从读锁升级到写锁
* 不可能。
*
* <li><b>Interruption of lock acquisition</b>
* <p>The read lock and write lock both support interruption during lock
* acquisition.
*
* 读锁和写锁在被获取期间,都容许中断
*
* <li><b>{@link Condition} support</b>
* <p>The write lock provides a {@link Condition} implementation that
* behaves in the same way, with respect to the write lock, as the
* {@link Condition} implementation provided by
* {@link ReentrantLock#newCondition} does for {@link ReentrantLock}.
* This {@link Condition} can, of course, only be used with the write lock.
*
* 支持{@link Condition}
* 写锁提供了一个跟{@link Condition}同样功能的实现,针对写锁,
* {@link ReentrantLock}的{@link Condition}被
* {@link ReentrantLock#newCondition}提供
* 当然,{@link Condition}只能和写锁一起使用
*
*
*
* <p>The read lock does not support a {@link Condition} and
* {@code readLock().newCondition()} throws
* {@code UnsupportedOperationException}.
* 读锁不支持{@link Condition}
*
* <li><b>Instrumentation</b>
* <p>This class supports methods to determine whether locks
* are held or contended. These methods are designed for monitoring
* system state, not for synchronization control.
* </ul>
*
* 仪器仪表
* < p >此类支持确定锁是否
* 被持有或争夺。这些方法是为监控系统状态设计的
* ,不用于同步控制。
*
* <p>Serialization of this class behaves in the same way as built-in
* locks: a deserialized lock is in the unlocked state, regardless of
* its state when serialized.
*
* 该类的序列化行为与内置的锁方式相同
* :反序列化的锁处于解锁状态,无论
* 序列化时锁的状态是什么。
*
* <p><b>Sample usages</b>. Here is a code sketch showing how to perform
* lock downgrading after updating a cache (exception handling is
* particularly tricky when handling multiple locks in a non-nested
* fashion):
* 使用示例
* 更新缓存后执行锁降级(当以非嵌套的方式处理多个锁时,异常处理是比较困难的)
*
* <pre> {@code
* class CachedData {
* Object data;
* volatile boolean cacheValid;
* final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
*
* void processCachedData() {
* rwl.readLock().lock();
* if (!cacheValid) {
* // Must release read lock before acquiring write lock
* rwl.readLock().unlock();
* rwl.writeLock().lock();
* try {
* // Recheck state because another thread might have
* // acquired write lock and changed state before we did.
* if (!cacheValid) {
* data = ...
* cacheValid = true;
* }
* // Downgrade by acquiring read lock before releasing write lock
* rwl.readLock().lock();
* } finally {
* rwl.writeLock().unlock(); // Unlock write, still hold read
* }
* }
*
* try {
* use(data);
* } finally {
* rwl.readLock().unlock();
* }
* }
* }}</pre>
*
* ReentrantReadWriteLocks can be used to improve concurrency in some
* uses of some kinds of Collections. This is typically worthwhile
* only when the collections are expected to be large, accessed by
* more reader threads than writer threads, and entail operations with
* overhead that outweighs synchronization overhead. For example, here
* is a class using a TreeMap that is expected to be large and
* concurrently accessed.
*
* ReentrantReadWriteLocks可用于提高某些集合的并发性。
* 仅当集合预计很大时,
* 读线程比写线程多,并且需要用
* 超过同步开销的开销时,使用ReentrantReadWriteLocks通常是值得的。比如这里
* 是一个使用TreeMap的类,该类应该很大并且
* 并发访问。
*
* <pre> {@code
* class RWDictionary {
* private final Map<String, Data> m = new TreeMap<String, Data>();
* private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
* private final Lock r = rwl.readLock();
* private final Lock w = rwl.writeLock();
*
* public Data get(String key) {
* r.lock();
* try { return m.get(key); }
* finally { r.unlock(); }
* }
* public String[] allKeys() {
* r.lock();
* try { return m.keySet().toArray(); }
* finally { r.unlock(); }
* }
* public Data put(String key, Data value) {
* w.lock();
* try { return m.put(key, value); }
* finally { w.unlock(); }
* }
* public void clear() {
* w.lock();
* try { m.clear(); }
* finally { w.unlock(); }
* }
* }}</pre>
*
* <h3>Implementation Notes</h3>
* 实施说明
* <p>This lock supports a maximum of 65535 recursive write locks
* and 65535 read locks. Attempts to exceed these limits result in
* {@link Error} throws from locking methods.
*
* 此锁最多支持65535个递归写锁
* 和65535读锁。试图超过这些限制会从锁方法抛出
* {@link Error}异常。
*
* @since 1.5
* @author Doug Lea
*/
public class ReentrantReadWriteLock {
}
WriteLock的lock方法(互斥锁,既检查读锁也检查写锁)
/**
* 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.
*
* 如果读锁和写锁都没有被另一个线程持有,马上获得一个写锁,并且设置写锁的记录数为1
*
* <p>If the current thread already holds the write lock then the
* hold count is incremented by one and the method returns
* immediately.
*
* 如果当前线程已经持有写锁,那么
* 保持计数增加1,方法马上返回。
*
* <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.
*
* 如果锁被另一个线程持有,那么当前的
* 出于线程调度的目的,线程被禁用
* 并且休眠,直到获得写锁,此时
* 写锁定记录数设置为1。
*/
public void lock() {
sync.acquire(1);
}
ReadLock的lock方法(共享锁,只检查写锁)
/**
* Acquires the read lock.
* 获取读锁。
*
* <p>Acquires the read lock if the write lock is not held by
* another thread and returns immediately.
*
* < p >如果写锁没有被另一个线程持有,则马上获得读锁。
*
* <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);
}