并发编程之ReadWriteLock读写锁
Posted 沸羊羊一个
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发编程之ReadWriteLock读写锁相关的知识,希望对你有一定的参考价值。
1、前言
ReadWriteLock是jdk5中提供得读写分离锁。读写分离锁可以有效地帮助减少锁竞争,以提高系统性能。
在实际应用中,如果读操作次数远大于写操作,则读写锁就可以发挥最大得功效,提升系统性能。
- 读读不互斥:读读之间不阻塞
- 读写互斥:读阻写,写也会阻读
- 写写互斥:写写阻塞
2、使用��
package package3;
import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 读读(非阻塞)、读写(阻塞)、写写(阻塞)
*
* 以下demo,不用读写锁,要花费20秒。 使用读写锁,远小于花费20秒
*/
public class ReadWriteLockDemo
private static Lock lock = new ReentrantLock();
private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();//实例化读写锁
private static Lock readLock = readWriteLock.readLock();//获取读锁
private static Lock writeLock = readWriteLock.writeLock();//获取写锁
private int value;
public int handleRead(Lock lock)
try
lock.lock();//模拟读操作
Thread.sleep(1000);//模拟耗时
catch (Exception e)
e.printStackTrace();
finally
lock.unlock();
return this.value;
public void handleWrite(Lock lock,int index)
try
lock.lock();
Thread.sleep(1000);
this.value = index;
catch (Exception e)
e.printStackTrace();
finally
lock.unlock();
public static void main(String[] args)
final ReadWriteLockDemo readWriteLockDemo = new ReadWriteLockDemo();
//读线程
Runnable readRunable = new Runnable()
@Override
public void run()
readWriteLockDemo.handleRead(readLock);
// readWriteLockDemo.handleRead(lock);
;
//写线程
Runnable writeRunable = new Runnable()
@Override
public void run()
readWriteLockDemo.handleWrite(writeLock,new Random().nextInt(1000));
//readWriteLockDemo.handleWrite(lock,new Random().nextInt(1000));
;
for (int i=0;i<18;i++)
new Thread(readRunable).start();
for (int i=18;i<20;i++)
new Thread(writeRunable).start();
由于采用读写锁,读读之间并行,节省了大量实际。整个程序大约2秒运行完成。如果不采用读写锁,程序执行将长达20秒。
3、Java并发-ReentrantReadWriteLock源码分析
4、ReentrantReadWriteLock源码
package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
import java.util.Collection;
public class ReentrantReadWriteLock
implements ReadWriteLock, java.io.Serializable
private static final long serialVersionUID = -6992448646407690164L;
/** 内部类读锁 */
private final ReentrantReadWriteLock.ReadLock readerLock;
/** 内部类写锁 */
private final ReentrantReadWriteLock.WriteLock writerLock;
/** 同步机制类 */
final Sync sync;
/**
*构造函数,默认不公平锁
*/
public ReentrantReadWriteLock()
this(false);
/**
* 构造函数
* @param fair 是否公平锁 true:公平 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;
/**
* reentrantreadwritelock同步的实现。
* 定义为公平和不公平两版本。
*/
abstract static class Sync extends AbstractQueuedSynchronizer
private static final long serialVersionUID = 6317671515068378041L;
/*
* 读写锁中最重要的就是Sync类,它继承自AQS。AQS使用一个int型来保存状态,状态在这里就代表锁,它提供了获取和修改状态的方法。
* 状态的高16位用作读锁(共享锁方式),低16位用作写锁(独占锁方式)
*/
//最多支持65535个写锁和65535个读锁;低16位表示写锁计数,高16位表示持有读锁的线程数
static final int SHARED_SHIFT = 16;
//由于读锁用高位部分,读锁个数加1,其实是状态值加 2^16
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
/**写锁的掩码,用于状态的低16位有效值 */
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
/** 读锁(共享锁)计数,当前持有读锁的线程数,c的高16位 */
static int sharedCount(int c) return c >>> SHARED_SHIFT;
/** 写锁(独占锁)的计数,也就是它的重入次数,c的低16位*/
static int exclusiveCount(int c) return c & EXCLUSIVE_MASK;
/**
* 每个线程持有读锁的计数
*/
static final class HoldCounter
int count = 0;
//使用id而不是引用是为了避免保留垃圾。注意这是个常量。
final long tid = getThreadId(Thread.currentThread());
/**
* 采用继承是为了重写 initialValue 方法,这样就不用进行这样的处理:
* 如果ThreadLocal没有当前线程的计数,则new一个,再放进ThreadLocal里。
* 可以直接调用 get。
* */
static final class ThreadLocalHoldCounter
extends ThreadLocal<HoldCounter>
public HoldCounter initialValue()
return new HoldCounter();
/**
* 当前线程持有的可重入读锁的数量,仅在构造方法和readObject(反序列化)
* 时被初始化,当持有锁的数量为0时,移除此对象。
*/
private transient ThreadLocalHoldCounter readHolds;
/**
* 最近一个成功获取读锁的线程的计数。这省却了ThreadLocal查找,
* 通常情况下,下一个释放线程是最后一个获取线程。这不是 volatile 的,
* 因为它仅用于试探的,线程进行缓存也是可以的
* (因为判断是否是当前线程是通过线程id来比较的)。
*/
private transient HoldCounter cachedHoldCounter;
/**firstReader是第一个获得读锁的线程;
* firstReaderHoldCount是firstReader的重入计数;
* 更准确的说,firstReader是最后一个把共享计数从0改为1,并且还没有释放锁。
* 如果没有这样的线程,firstReader为null;
* firstReader不会导致垃圾堆积,因为在tryReleaseShared中将它置空了,除非
* 线程异常终止,没有释放读锁。
*
* 跟踪无竞争的读锁计数时,代价很低
*/
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())//当前线程没有持有锁,抛异常
throw new IllegalMonitorStateException();
//获得一次锁,同步状态+1,释放时每释放一次同步状态-1,直到状态为0,可重入锁全部释放完毕。
int nextc = getState() - releases;
boolean free = exclusiveCount(nextc) == 0;
if (free)//如果锁是可用的
setExclusiveOwnerThread(null);//当前线程释放锁
setState(nextc);// 重入计数
return free;
//获取锁
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");
//执行到这里,说明存在写锁,且由当前线程持有
// 重入计数
setState(c + acquires);
return true;
//执行到这里,说明不存在任何锁
//WriterShouldBlock留给子类实现公平策略
//使用CAS修改状态
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires))
return false;
setExclusiveOwnerThread(current);
return true;
/**
* 释放读锁
*/
protected final boolean tryReleaseShared(int unused)
Thread current = Thread.currentThread();//获取当前线程
/**
* 当前线程是第一个获取到锁的,如果此线程要释放锁了,则firstReader置空
* 否则,将线程持有的锁计数减1
*/
if (firstReader == current)
// assert firstReaderHoldCount > 0;
if (firstReaderHoldCount == 1)
firstReader = null;
else
firstReaderHoldCount--;
else
HoldCounter rh = cachedHoldCounter;
//如果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;
private IllegalMonitorStateException unmatchedUnlockException()
return new IllegalMonitorStateException(
"attempt to unlock read lock, not locked by current thread");
//Sync中的tryAcquireShared 尝试获取读锁
protected final int tryAcquireShared(int unused)
/*
(1)如果当前写锁被其他线程持有,则获取读锁失败;
(2)写锁空闲,或者写锁被当前线程持有(写锁可降级为读锁),在公平策略下,它可能需要阻塞,那么tryAcquireShared()就可能失败,则需要进入队列等待;
如果是非公平策略,会尝试获取锁,使用CAS修改状态,修改成功,则获得读锁,否则也会进入同步队列等待;
(3)进入同步队列后,就是由AQS来完成唤醒。
*/
Thread current = Thread.currentThread();//获取当前线程
int c = getState();//同步获取状态
/*** 持有写锁的线程可以获得读锁 **/
if (exclusiveCount(c) != 0 && //写锁被占用
getExclusiveOwnerThread() != current) //且不是由当前线程持有
return -1;
/******** 执行到这里表明:写锁可用,或者写锁由当前线程持有 *****/
//获得读锁的数量
int r = sharedCount(c);
/** 如果读锁没有阻塞,且没有溢出,则使用CAS修改状态,并且修改成功 */
if (!readerShouldBlock() &&
r < MAX_COUNT &&
compareAndSetState(c, c + SHARED_UNIT)) //修改高16位的状态,所以要加上2^16
//这是第一个占有读锁的线程,所以设置firstReader
if (r == 0)
firstReader = current;
firstReaderHoldCount = 1;
else if (firstReader == current)
firstReaderHoldCount++;//重入计数加1
else
// 非 firstReader 读锁重入计数更新
//将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 1;
//获取读锁失败,放到循环里重试
return fullTryAcquireShared(current);
/**
* 处理读写失败的完整读取版本
* 和tryacquireshared不同在于,此方法循环获取锁
*/
final int fullTryAcquireShared(Thread current)
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
if (firstReader == current) //当前线程是第一个占有读锁的线程
// assert firstReaderHoldCount > 0;
else //当前线程不是第一个占有读锁的线程
if (rh == null)
//将cachedHoldCounter设置为当前线程
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)) //修改高16位的状态,所以要加上2^16
//这是第一个占有读锁的线程,所以设置firstReader
if (sharedCount(c) == 0)
firstReader = current;
firstReaderHoldCount = 1;
else if (firstReader == current) //重入计数加1
firstReaderHoldCount++;
else
// 非 firstReader 读锁重入计数更新
//将cachedHoldCounter设置为当前线程
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.
*/
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;
/**
* Performs tryLock for read, enabling barging in both modes.
* This is identical in effect to tryAcquireShared except for
* lack of calls to readerShouldBlock.
*/
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();
// 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();
/**
* 非公平同步锁
*/
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.
*/
return apparentlyFirstQueuedIsExclusive();
/**
* 公平同步锁
*/
static final class FairSync extends Sync
private static final long serialVersionUID = -2274990926593161451L;
final boolean writerShouldBlock()
return hasQueuedPredecessors();
final boolean readerShouldBlock()
return hasQueuedPredecessors();
/**
* The lock returned by method @link ReentrantReadWriteLock#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;
/**
* 获取读锁,如果写锁不是由其他线程持有,则获取并立即返回;
* 如果写锁被其他线程持有,阻塞,直到读锁被获得。
*/
public void lock()
sync.acquireShared(1);
//ASQ的acquireShared
/**
* 以共享模式获取对象,忽略中断。通过至少先调用一次 tryAcquireShared(int)
* 来实现此方法,并在成功时返回。否则在成功之前,一直调用 tryAcquireShared(int)
* 将线程加入队列,线程可能重复被阻塞或不被阻塞。
*/
/*public final void acquireShared(int arg)
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
*/
/**
* 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
*/
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 + "]";
/**
* The lock returned by method @link ReentrantReadWriteLock#writeLock.
*/
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 以上是关于并发编程之ReadWriteLock读写锁的主要内容,如果未能解决你的问题,请参考以下文章