|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object jsr166e.SequenceLock
public class SequenceLock
A reentrant mutual exclusion 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);
}
}
Constructor Summary | |
---|---|
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. |
Method Summary | |
---|---|
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. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
Constructor Detail |
---|
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.
Method Detail |
---|
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 argument
InterruptedException
- if the current thread is interrupted
TimeoutException
- if the lock was not available within
the specified waiting time
NullPointerException
- 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.
lock
in interface 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
in interface Lock
InterruptedException
- 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
.
tryLock
in interface Lock
true
if the lock was free and was acquired by the
current thread, or the lock was already held by the current
thread; and false
otherwisepublic 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
in interface Lock
timeout
- the time to wait for the lockunit
- the time unit of the timeout argument
true
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 acquired
InterruptedException
- if the current thread is interrupted
NullPointerException
- 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
in interface Lock
IllegalMonitorStateException
- if the current thread does not
hold this lockpublic Condition newCondition()
newCondition
in interface Lock
UnsupportedOperationException
public 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 thread
true
if the given thread is queued waiting for this lock
NullPointerException
- if the thread is nullpublic final int getQueueLength()
protected Collection<Thread> getQueuedThreads()
public String toString()
"Unlocked"
or the String "Locked by"
followed by the
name of the owning thread.
toString
in class Object
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |