reentrantreadwritelock.java
来自「SRI international 发布的OAA框架软件」· Java 代码 · 共 1,180 行 · 第 1/4 页
JAVA
1,180 行
return readerLock_;
else if (waitingWriters_ > 0)
return writerLock_;
else
return null;
}
}
/**
* Reader and Writer requests are maintained in two different
* wait sets, by two different objects. These objects do not
* know whether the wait sets need notification since they
* don't know preference rules. So, each supports a
* method that can be selected by main controlling object
* to perform the notifications. This base class simplifies mechanics.
*/
static interface Signaller { // base for ReaderLock and WriterLock
void signalWaiters();
}
class ReaderLock implements Signaller, Lock, java.io.Serializable {
/**
* 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() {
boolean wasInterrupted = false;
while (true) {
try {
lockInterruptibly();
if (wasInterrupted) {
Thread.currentThread().interrupt();
}
return;
}
catch (InterruptedException e) {
wasInterrupted = true;
}
}
}
/**
* Acquires the read lock unless the current thread is
* {@link 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 {@link 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 {@link 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 {
if (Thread.interrupted())
throw new InterruptedException();
InterruptedException ie = null;
synchronized (this) {
if (!startReadFromNewReader()) {
for (; ; ) {
try {
ReaderLock.this.wait();
if (startReadFromWaitingReader())
return;
}
catch (InterruptedException ex) {
cancelledWaitingReader();
ie = ex;
break;
}
}
}
}
if (ie != null) {
// fall through outside synch on interrupt.
// This notification is not really needed here,
// but may be in plausible subclasses
writerLock_.signalWaiters();
throw ie;
}
}
/**
* 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() {
Signaller s = endRead();
if (s != null)
s.signalWaiters();
}
public synchronized void signalWaiters() {
ReaderLock.this.notifyAll();
}
/**
* 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
* <tt>true</tt>. Even when this lock has been set to use a
* fair ordering policy, a call to <tt>tryLock()</tt>
* <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
* <tt>false</tt>.
*
* @return <tt>true</tt> if the read lock was acquired.
*/
public boolean tryLock() {
return startRead();
}
/**
* 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 {@link Thread#interrupt
* interrupted}.
*
* <p>Acquires the read lock if the write lock is not held by
* another thread and returns immediately with the value
* <tt>true</tt>. 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 <tt>tryLock</tt> that does
* permit barging on a fair lock then combine the timed and
* un-timed forms together:
*
* <pre>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 {@link Thread#interrupt interrupts} the current
* thread; or
*
* <li>The specified waiting time elapses
*
* </ul>
*
* <p>If the read lock is acquired then the value <tt>true</tt> is
* returned.
*
* <p>If the current thread:
*
* <ul>
*
* <li>has its interrupted status set on entry to this method; or
*
* <li>is {@link 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
* <tt>false</tt> 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 <tt>true</tt> if the read lock was acquired.
*
* @throws InterruptedException if the current thread is interrupted
* @throws NullPointerException if unit is null
*
*/
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
if (Thread.interrupted()) throw new InterruptedException();
InterruptedException ie = null;
long nanos = unit.toNanos(timeout);
synchronized (this) {
if (nanos <= 0)
return startRead();
else if (startReadFromNewReader())
return true;
else {
long deadline = Utils.nanoTime() + nanos;
for (; ; ) {
try {
TimeUnit.NANOSECONDS.timedWait(ReaderLock.this, nanos);
}
catch (InterruptedException ex) {
cancelledWaitingReader();
ie = ex;
break;
}
if (startReadFromWaitingReader())
return true;
else {
nanos = deadline - Utils.nanoTime();
if (nanos <= 0) {
cancelledWaitingReader();
break;
}
}
}
}
}
// safeguard on interrupt or timeout:
writerLock_.signalWaiters();
if (ie != null)
throw ie;
else
return false; // timed out
}
/**
* Throws <tt>UnsupportedOperationException</tt> because
* <tt>ReadLocks</tt> 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
* "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 = getReadLockCount();
return super.toString() +
"[Read locks = " + r + "]";
}
}
class WriterLock implements Signaller, Lock, java.io.Serializable,
CondVar.LockInfo {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?