public class SequenceLock extends Object implements Lock, Serializable
Lock in which each lock acquisition or
release advances a sequence number. When the sequence number (accessible
using getSequence()) is odd, the lock is held. When it is even
(i.e., (lock.getSequence()
& 1L) == 0L), the lock is released. Method awaitAvailability() can be used to await availability of the lock, returning
its current sequence number. Sequence numbers (as well as reentrant hold
counts) are of type long to ensure that they will not wrap around
until hundreds of years of use under current processor rates. A SequenceLock
can be created with a specified number of spins. Attempts to acquire the lock
in method lock() will retry at least the given number of times before blocking. If not
specified, a default, possibly platform-specific, value is used.
Except for the lack of support for specified fairness policies, or
Condition objects, a SequenceLock can be used in the same way as
ReentrantLock. It provides similar status and monitoring methods,
such as isHeldByCurrentThread(). SequenceLocks may be preferable in
contexts in which multiple threads invoke short read-only methods much more
frequently than fully locked methods.
Methods awaitAvailability and getSequence can be used
together to define (partially) optimistic read-only methods that are usually
more efficient than ReadWriteLocks when they apply. These methods should in
general be structured as loops that await lock availability, then read
volatile fields into local variables (and may further read other
values derived from these, for example the length of a
volatile array), and retry if the sequence number changed while doing
so. Alternatively, because awaitAvailability accommodates reentrancy,
a method can retry a bounded number of times before switching to locking
mode. While conceptually straightforward, expressing these ideas can be
verbose. For example:
class Point {
private volatile double x, y;
private final SequenceLock sl = new SequenceLock();
// an exclusively locked method
void move(double deltaX, double deltaY) {
sl.lock();
try {
x += deltaX;
y += deltaY;
} finally {
sl.unlock();
}
}
// A read-only method
double distanceFromOriginV1() {
double currentX, currentY;
long seq;
do {
seq = sl.awaitAvailability();
currentX = x;
currentY = y;
} while (sl.getSequence() != seq); // retry if sequence changed
return Math.sqrt(currentX * currentX + currentY * currentY);
}
// Uses bounded retries before locking
double distanceFromOriginV2() {
double currentX, currentY;
long seq;
int retries = RETRIES_BEFORE_LOCKING; // for example 8
try {
do {
if (--retries < 0)
sl.lock();
seq = sl.awaitAvailability();
currentX = x;
currentY = y;
} while (sl.getSequence() != seq);
} finally {
if (retries < 0)
sl.unlock();
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}
}| 构造器和说明 |
|---|
SequenceLock()
Creates an instance of
SequenceLock with the default number of
retry attempts to acquire the lock before blocking. |
SequenceLock(int spins)
Creates an instance of
SequenceLock that will retry attempts to
acquire the lock at least the given number times before blocking. |
| 限定符和类型 | 方法和说明 |
|---|---|
long |
awaitAvailability()
Returns the current sequence number when the lock is, or becomes,
available.
|
long |
getHoldCount()
Queries the number of holds on this lock by the current thread.
|
protected Thread |
getOwner()
Returns the thread that currently owns this lock, or
null if not
owned. |
protected Collection<Thread> |
getQueuedThreads()
Returns a collection containing threads that may be waiting to acquire
this lock.
|
int |
getQueueLength()
Returns an estimate of the number of threads waiting to acquire this
lock.
|
long |
getSequence()
Returns the current sequence number of this lock.
|
boolean |
hasQueuedThread(Thread thread)
Queries whether the given thread is waiting to acquire this lock.
|
boolean |
hasQueuedThreads()
Queries whether any threads are waiting to acquire this lock.
|
boolean |
isHeldByCurrentThread()
Queries if this lock is held by the current thread.
|
boolean |
isLocked()
Queries if this lock is held by any thread.
|
void |
lock()
Acquires the lock.
|
void |
lockInterruptibly()
Acquires the lock unless the current thread is
interrupted.
|
Condition |
newCondition()
Throws UnsupportedOperationException.
|
String |
toString()
Returns a string identifying this lock, as well as its lock state.
|
long |
tryAwaitAvailability(long timeout,
TimeUnit unit)
Returns the current sequence number if the lock is, or becomes, available
within the specified waiting time.
|
boolean |
tryLock()
Acquires the lock only if it is not held by another thread at the time of
invocation.
|
boolean |
tryLock(long timeout,
TimeUnit unit)
Acquires the lock if it is not held by another thread within the given
waiting time and the current thread has not been
interrupted.
|
void |
unlock()
Attempts to release this lock.
|
public SequenceLock()
SequenceLock with the default number of
retry attempts to acquire the lock before blocking.public SequenceLock(int spins)
SequenceLock that will retry attempts to
acquire the lock at least the given number times before blocking.public long getSequence()
public long awaitAvailability()
public long tryAwaitAvailability(long timeout,
TimeUnit unit)
throws InterruptedException,
TimeoutException
If the lock is not available, the current thread becomes disabled for thread scheduling purposes and lies dormant until one of three things happens:
InterruptedException.
TimeoutException.
timeout - the time to wait for availabilityunit - the time unit of the timeout argumentInterruptedException - if the current thread is interruptedTimeoutException - if the lock was not available within the
specified waiting timeNullPointerException - if the time unit is nullpublic void lock()
If the current thread already holds this lock then the hold count is incremented by one and the method returns immediately without incrementing the sequence number.
If this lock not held by another thread, this method increments the sequence number (which thus becomes an odd number), sets the lock hold count to one, and returns immediately.
If the lock is held by another thread then the current thread may
retry acquiring this lock, depending on the spin count established in constructor. If the lock is still not
acquired, the current thread becomes disabled for thread scheduling
purposes and lies dormant until enabled by some other thread releasing
the lock.
public void lockInterruptibly()
throws InterruptedException
If the current thread already holds this lock then the hold count is incremented by one and the method returns immediately without incrementing the sequence number.
If this lock not held by another thread, this method increments the sequence number (which thus becomes an odd number), sets the lock hold count to one, and returns immediately.
If the lock is held by another thread then the current thread may
retry acquiring this lock, depending on the spin count established in constructor. If the lock is still not
acquired, the current thread becomes disabled for thread scheduling
purposes and lies dormant until one of two things happens:
If the lock is acquired by the current thread then the lock hold count is set to one and the sequence number is incremented.
If the current thread:
InterruptedException is thrown and the current thread's
interrupted status is cleared.
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.
lockInterruptibly 在接口中 LockInterruptedException - if the current thread is interruptedpublic boolean tryLock()
If the current thread already holds this lock then the hold count is
incremented by one and the method returns true without
incrementing the sequence number.
If this lock not held by another thread, this method increments the
sequence number (which thus becomes an odd number), sets the lock hold
count to one, and returns true.
If the lock is held by another thread then this method returns
false.
public boolean tryLock(long timeout,
TimeUnit unit)
throws InterruptedException
If the current thread already holds this lock then the hold count is incremented by one and the method returns immediately without incrementing the sequence number.
If this lock not held by another thread, this method increments the sequence number (which thus becomes an odd number), sets the lock hold count to one, and returns immediately.
If the lock is held by another thread then the current thread may
retry acquiring this lock, depending on the spin count established in constructor. If the lock is still not
acquired, the current thread becomes disabled for thread scheduling
purposes and lies dormant until one of three things happens:
If the lock is acquired then the value true is returned and
the lock hold count is set to one.
If the current thread:
InterruptedException is thrown and the current thread's
interrupted status is cleared.
If the specified waiting time elapses then the value false is
returned. If the time is less than or equal to zero, the method will not
wait at all.
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.
tryLock 在接口中 Locktimeout - the time to wait for the lockunit - the time unit of the timeout argumenttrue if the lock was free and was acquired by the current
thread, or the lock was already held by the current thread; and
false if the waiting time elapsed before the lock could be
acquiredInterruptedException - if the current thread is interruptedNullPointerException - if the time unit is nullpublic void unlock()
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 sequence number is
incremented (thus becoming an even number) and the lock is released. If
the current thread is not the holder of this lock then IllegalMonitorStateException is thrown.
unlock 在接口中 LockIllegalMonitorStateException - if the current thread does not hold
this lockpublic Condition newCondition()
newCondition 在接口中 LockUnsupportedOperationExceptionpublic long getHoldCount()
A thread has a hold on a lock for each lock action that is not matched by an unlock action.
The hold count information is typically only used for testing and debugging purposes.
public boolean isHeldByCurrentThread()
true if current thread holds this lock and false
otherwisepublic boolean isLocked()
true if any thread holds this lock and false
otherwiseprotected Thread getOwner()
null if not
owned. When this method is called by a thread that is not the owner, the
return value reflects a best-effort approximation of current lock status.
For example, the owner may be momentarily null even if there are
threads trying to acquire the lock but have not yet done so. This method
is designed to facilitate construction of subclasses that provide more
extensive lock monitoring facilities.null if not ownedpublic final boolean hasQueuedThreads()
true return does
not guarantee that any other thread will ever acquire this lock. This
method is designed primarily for use in monitoring of the system state.true if there may be other threads waiting to acquire the
lockpublic final boolean hasQueuedThread(Thread thread)
true return
does not guarantee that this thread will ever acquire this lock. This
method is designed primarily for use in monitoring of the system state.thread - the threadtrue if the given thread is queued waiting for this lockNullPointerException - if the thread is nullpublic final int getQueueLength()
protected Collection<Thread> getQueuedThreads()
Copyright © 2013 The Skfiy Open Association. All Rights Reserved.