Methods Summary |
---|
public final void | acquire(long arg)Acquires in exclusive mode, ignoring interrupts. Implemented
by invoking at least once {@link #tryAcquire},
returning on success. Otherwise the thread is queued, possibly
repeatedly blocking and unblocking, invoking {@link
#tryAcquire} until success. This method can be used
to implement method {@link Lock#lock}.
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
|
public final void | acquireInterruptibly(long arg)Acquires in exclusive mode, aborting if interrupted.
Implemented by first checking interrupt status, then invoking
at least once {@link #tryAcquire}, returning on
success. Otherwise the thread is queued, possibly repeatedly
blocking and unblocking, invoking {@link #tryAcquire}
until success or the thread is interrupted. This method can be
used to implement method {@link Lock#lockInterruptibly}.
if (Thread.interrupted())
throw new InterruptedException();
if (!tryAcquire(arg))
doAcquireInterruptibly(arg);
|
final boolean | acquireQueued(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node node, long arg)Acquires in exclusive uninterruptible mode for thread already in
queue. Used by condition wait methods as well as acquire.
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} catch (RuntimeException ex) {
cancelAcquire(node);
throw ex;
}
|
public final void | acquireShared(long arg)Acquires in shared mode, ignoring interrupts. Implemented by
first invoking at least once {@link #tryAcquireShared},
returning on success. Otherwise the thread is queued, possibly
repeatedly blocking and unblocking, invoking {@link
#tryAcquireShared} until success.
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
|
public final void | acquireSharedInterruptibly(long arg)Acquires in shared mode, aborting if interrupted. Implemented
by first checking interrupt status, then invoking at least once
{@link #tryAcquireShared}, returning on success. Otherwise the
thread is queued, possibly repeatedly blocking and unblocking,
invoking {@link #tryAcquireShared} until success or the thread
is interrupted.
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
|
private java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node | addWaiter(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node mode)Creates and enqueues node for given thread and mode.
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
|
final boolean | apparentlyFirstQueuedIsExclusive()Return {@code true} if the apparent first queued thread, if one
exists, is not waiting in exclusive mode. Used only as a heuristic
in ReentrantReadWriteLock.
Node h, s;
return ((h = head) != null && (s = h.next) != null &&
s.nextWaiter != Node.SHARED);
|
private void | cancelAcquire(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node node)Cancels an ongoing attempt to acquire.
// Ignore if node doesn't exist
if (node == null)
return;
node.thread = null;
// Skip cancelled predecessors
Node pred = node.prev;
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
// Getting this before setting waitStatus ensures staleness
Node predNext = pred.next;
// Can use unconditional write instead of CAS here
node.waitStatus = Node.CANCELLED;
// If we are the tail, remove ourselves
if (node == tail && compareAndSetTail(node, pred)) {
compareAndSetNext(pred, predNext, null);
} else {
// If "active" predecessor found...
if (pred != head
&& (pred.waitStatus == Node.SIGNAL
|| compareAndSetWaitStatus(pred, 0, Node.SIGNAL))
&& pred.thread != null) {
// If successor is active, set predecessor's next link
Node next = node.next;
if (next != null && next.waitStatus <= 0)
compareAndSetNext(pred, predNext, next);
} else {
unparkSuccessor(node);
}
node.next = node; // help GC
}
|
private final boolean | compareAndSetHead(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node update)CAS head field. Used only by enq
try {
stateOffset = unsafe.objectFieldOffset
(AbstractQueuedLongSynchronizer.class.getDeclaredField("state"));
headOffset = unsafe.objectFieldOffset
(AbstractQueuedLongSynchronizer.class.getDeclaredField("head"));
tailOffset = unsafe.objectFieldOffset
(AbstractQueuedLongSynchronizer.class.getDeclaredField("tail"));
waitStatusOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("waitStatus"));
nextOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("next"));
} catch (Exception ex) { throw new Error(ex); }
return unsafe.compareAndSwapObject(this, headOffset, null, update);
|
private static final boolean | compareAndSetNext(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node node, java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node expect, java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node update)CAS next field of a node.
return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
|
protected final boolean | compareAndSetState(long expect, long update)Atomically sets synchronization state to the given updated
value if the current state value equals the expected value.
This operation has memory semantics of a volatile read
and write.
// See below for intrinsics setup to support this
return unsafe.compareAndSwapLong(this, stateOffset, expect, update);
|
private final boolean | compareAndSetTail(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node expect, java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node update)CAS tail field. Used only by enq
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
|
private static final boolean | compareAndSetWaitStatus(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node node, int expect, int update)CAS waitStatus field of a node.
return unsafe.compareAndSwapInt(node, waitStatusOffset,
expect, update);
|
private void | doAcquireInterruptibly(long arg)Acquires in exclusive interruptible mode.
final Node node = addWaiter(Node.EXCLUSIVE);
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
return;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
break;
}
} catch (RuntimeException ex) {
cancelAcquire(node);
throw ex;
}
// Arrive here only if interrupted
cancelAcquire(node);
throw new InterruptedException();
|
private boolean | doAcquireNanos(long arg, long nanosTimeout)Acquires in exclusive timed mode.
long lastTime = System.nanoTime();
final Node node = addWaiter(Node.EXCLUSIVE);
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
return true;
}
if (nanosTimeout <= 0) {
cancelAcquire(node);
return false;
}
if (nanosTimeout > spinForTimeoutThreshold &&
shouldParkAfterFailedAcquire(p, node))
LockSupport.parkNanos(this, nanosTimeout);
long now = System.nanoTime();
nanosTimeout -= now - lastTime;
lastTime = now;
if (Thread.interrupted())
break;
}
} catch (RuntimeException ex) {
cancelAcquire(node);
throw ex;
}
// Arrive here only if interrupted
cancelAcquire(node);
throw new InterruptedException();
|
private void | doAcquireShared(long arg)Acquires in shared uninterruptible mode.
final Node node = addWaiter(Node.SHARED);
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head) {
long r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
if (interrupted)
selfInterrupt();
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} catch (RuntimeException ex) {
cancelAcquire(node);
throw ex;
}
|
private void | doAcquireSharedInterruptibly(long arg)Acquires in shared interruptible mode.
final Node node = addWaiter(Node.SHARED);
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
long r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
break;
}
} catch (RuntimeException ex) {
cancelAcquire(node);
throw ex;
}
// Arrive here only if interrupted
cancelAcquire(node);
throw new InterruptedException();
|
private boolean | doAcquireSharedNanos(long arg, long nanosTimeout)Acquires in shared timed mode.
long lastTime = System.nanoTime();
final Node node = addWaiter(Node.SHARED);
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
long r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
return true;
}
}
if (nanosTimeout <= 0) {
cancelAcquire(node);
return false;
}
if (nanosTimeout > spinForTimeoutThreshold &&
shouldParkAfterFailedAcquire(p, node))
LockSupport.parkNanos(this, nanosTimeout);
long now = System.nanoTime();
nanosTimeout -= now - lastTime;
lastTime = now;
if (Thread.interrupted())
break;
}
} catch (RuntimeException ex) {
cancelAcquire(node);
throw ex;
}
// Arrive here only if interrupted
cancelAcquire(node);
throw new InterruptedException();
|
private java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node | enq(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node node)Inserts node into queue, initializing if necessary. See picture above.
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
Node h = new Node(); // Dummy header
h.next = node;
node.prev = h;
if (compareAndSetHead(h)) {
tail = node;
return h;
}
}
else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
|
private boolean | findNodeFromTail(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node node)Returns true if node is on sync queue by searching backwards from tail.
Called only when needed by isOnSyncQueue.
Node t = tail;
for (;;) {
if (t == node)
return true;
if (t == null)
return false;
t = t.prev;
}
|
private java.lang.Thread | fullGetFirstQueuedThread()Version of getFirstQueuedThread called when fastpath fails
/*
* The first node is normally h.next. Try to get its
* thread field, ensuring consistent reads: If thread
* field is nulled out or s.prev is no longer head, then
* some other thread(s) concurrently performed setHead in
* between some of our reads. We try this twice before
* resorting to traversal.
*/
Node h, s;
Thread st;
if (((h = head) != null && (s = h.next) != null &&
s.prev == head && (st = s.thread) != null) ||
((h = head) != null && (s = h.next) != null &&
s.prev == head && (st = s.thread) != null))
return st;
/*
* Head's next field might not have been set yet, or may have
* been unset after setHead. So we must check to see if tail
* is actually first node. If not, we continue on, safely
* traversing from tail back to head to find first,
* guaranteeing termination.
*/
Node t = tail;
Thread firstThread = null;
while (t != null && t != head) {
Thread tt = t.thread;
if (tt != null)
firstThread = tt;
t = t.prev;
}
return firstThread;
|
final boolean | fullIsFirst(java.lang.Thread current)
// same idea as fullGetFirstQueuedThread
Node h, s;
Thread firstThread = null;
if (((h = head) != null && (s = h.next) != null &&
s.prev == head && (firstThread = s.thread) != null))
return firstThread == current;
Node t = tail;
while (t != null && t != head) {
Thread tt = t.thread;
if (tt != null)
firstThread = tt;
t = t.prev;
}
return firstThread == current || firstThread == null;
|
final long | fullyRelease(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node node)Invokes release with current state value; returns saved state.
Cancels node and throws exception on failure.
try {
long savedState = getState();
if (release(savedState))
return savedState;
} catch (RuntimeException ex) {
node.waitStatus = Node.CANCELLED;
throw ex;
}
// reach here if release fails
node.waitStatus = Node.CANCELLED;
throw new IllegalMonitorStateException();
|
public final java.util.Collection | getExclusiveQueuedThreads()Returns a collection containing threads that may be waiting to
acquire in exclusive mode. This has the same properties
as {@link #getQueuedThreads} except that it only returns
those threads waiting due to an exclusive acquire.
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node p = tail; p != null; p = p.prev) {
if (!p.isShared()) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
}
return list;
|
public final java.lang.Thread | getFirstQueuedThread()Returns the first (longest-waiting) thread in the queue, or
{@code null} if no threads are currently queued.
In this implementation, this operation normally returns in
constant time, but may iterate upon contention if other threads are
concurrently modifying the queue.
// handle only fast path, else relay
return (head == tail)? null : fullGetFirstQueuedThread();
|
public final int | getQueueLength()Returns an estimate of the number of threads waiting to
acquire. The value is only an estimate because the number of
threads may change dynamically while this method traverses
internal data structures. This method is designed for use in
monitoring system state, not for synchronization
control.
int n = 0;
for (Node p = tail; p != null; p = p.prev) {
if (p.thread != null)
++n;
}
return n;
|
public final java.util.Collection | getQueuedThreads()Returns a collection containing threads that may be waiting to
acquire. Because the actual set of threads may change
dynamically while constructing this result, the returned
collection is only a best-effort estimate. The elements of the
returned collection are in no particular order. This method is
designed to facilitate construction of subclasses that provide
more extensive monitoring facilities.
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node p = tail; p != null; p = p.prev) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
return list;
|
public final java.util.Collection | getSharedQueuedThreads()Returns a collection containing threads that may be waiting to
acquire in shared mode. This has the same properties
as {@link #getQueuedThreads} except that it only returns
those threads waiting due to a shared acquire.
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node p = tail; p != null; p = p.prev) {
if (p.isShared()) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
}
return list;
|
protected final long | getState()Returns the current value of synchronization state.
This operation has memory semantics of a volatile read.
return state;
|
public final int | getWaitQueueLength(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$ConditionObject condition)Returns an estimate of the number of threads waiting on the
given condition associated with this synchronizer. Note that
because timeouts and interrupts may occur at any time, the
estimate serves only as an upper bound on the actual number of
waiters. This method is designed for use in monitoring of the
system state, not for synchronization control.
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.getWaitQueueLength();
|
public final java.util.Collection | getWaitingThreads(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$ConditionObject condition)Returns a collection containing those threads that may be
waiting on the given condition associated with this
synchronizer. Because the actual set of threads may change
dynamically while constructing this result, the returned
collection is only a best-effort estimate. The elements of the
returned collection are in no particular order.
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.getWaitingThreads();
|
public final boolean | hasContended()Queries whether any threads have ever contended to acquire this
synchronizer; that is if an acquire method has ever blocked.
In this implementation, this operation returns in
constant time.
return head != null;
|
public final boolean | hasQueuedThreads()Queries whether any threads are waiting to acquire. Note that
because cancellations due to interrupts and timeouts may occur
at any time, a {@code true} return does not guarantee that any
other thread will ever acquire.
In this implementation, this operation returns in
constant time.
return head != tail;
|
public final boolean | hasWaiters(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$ConditionObject condition)Queries whether any threads are waiting on the given condition
associated with this synchronizer. Note that because timeouts
and interrupts may occur at any time, a true return
does not guarantee that a future signal will awaken
any threads. This method is designed primarily for use in
monitoring of the system state.
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.hasWaiters();
|
final boolean | isFirst(java.lang.Thread current)Return {@code true} if the queue is empty or if the given thread
is at the head of the queue. This is reliable only if
current is actually Thread.currentThread() of caller.
Node h, s;
return ((h = head) == null ||
((s = h.next) != null && s.thread == current) ||
fullIsFirst(current));
|
protected boolean | isHeldExclusively()Returns {@code true} if synchronization is held exclusively with
respect to the current (calling) thread. This method is invoked
upon each call to a non-waiting {@link ConditionObject} method.
(Waiting methods instead invoke {@link #release}.)
The default implementation throws {@link
UnsupportedOperationException}. This method is invoked
internally only within {@link ConditionObject} methods, so need
not be defined if conditions are not used.
throw new UnsupportedOperationException();
|
final boolean | isOnSyncQueue(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node node)Returns true if a node, always one that was initially placed on
a condition queue, is now waiting to reacquire on sync queue.
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
if (node.next != null) // If has successor, it must be on queue
return true;
/*
* node.prev can be non-null, but not yet on queue because
* the CAS to place it on queue can fail. So we have to
* traverse from tail to make sure it actually made it. It
* will always be near the tail in calls to this method, and
* unless the CAS failed (which is unlikely), it will be
* there, so we hardly ever traverse much.
*/
return findNodeFromTail(node);
|
public final boolean | isQueued(java.lang.Thread thread)Returns true if the given thread is currently queued.
This implementation traverses the queue to determine
presence of the given thread.
if (thread == null)
throw new NullPointerException();
for (Node p = tail; p != null; p = p.prev)
if (p.thread == thread)
return true;
return false;
|
public final boolean | owns(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$ConditionObject condition)Queries whether the given ConditionObject
uses this synchronizer as its lock.
if (condition == null)
throw new NullPointerException();
return condition.isOwnedBy(this);
|
private final boolean | parkAndCheckInterrupt()Convenience method to park and then check if interrupted
LockSupport.park(this);
return Thread.interrupted();
|
public final boolean | release(long arg)Releases in exclusive mode. Implemented by unblocking one or
more threads if {@link #tryRelease} returns true.
This method can be used to implement method {@link Lock#unlock}.
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
|
public final boolean | releaseShared(long arg)Releases in shared mode. Implemented by unblocking one or more
threads if {@link #tryReleaseShared} returns true.
if (tryReleaseShared(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
|
private static void | selfInterrupt()Convenience method to interrupt current thread.
Thread.currentThread().interrupt();
|
private void | setHead(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node node)Sets head of queue to be node, thus dequeuing. Called only by
acquire methods. Also nulls out unused fields for sake of GC
and to suppress unnecessary signals and traversals.
head = node;
node.thread = null;
node.prev = null;
|
private void | setHeadAndPropagate(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node node, long propagate)Sets head of queue, and checks if successor may be waiting
in shared mode, if so propagating if propagate > 0.
setHead(node);
if (propagate > 0 && node.waitStatus != 0) {
/*
* Don't bother fully figuring out successor. If it
* looks null, call unparkSuccessor anyway to be safe.
*/
Node s = node.next;
if (s == null || s.isShared())
unparkSuccessor(node);
}
|
protected final void | setState(long newState)Sets the value of synchronization state.
This operation has memory semantics of a volatile write.
state = newState;
|
private static boolean | shouldParkAfterFailedAcquire(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node pred, java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node node)Checks and updates status for a node that failed to acquire.
Returns true if thread should block. This is the main signal
control in all acquire loops. Requires that pred == node.prev
int s = pred.waitStatus;
if (s < 0)
/*
* This node has already set status asking a release
* to signal it, so it can safely park
*/
return true;
if (s > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
}
else
/*
* Indicate that we need a signal, but don't park yet. Caller
* will need to retry to make sure it cannot acquire before
* parking.
*/
compareAndSetWaitStatus(pred, 0, Node.SIGNAL);
return false;
|
public java.lang.String | toString()Returns a string identifying this synchronizer, as well as its state.
The state, in brackets, includes the String {@code "State ="}
followed by the current value of {@link #getState}, and either
{@code "nonempty"} or {@code "empty"} depending on whether the
queue is empty.
long s = getState();
String q = hasQueuedThreads()? "non" : "";
return super.toString() +
"[State = " + s + ", " + q + "empty queue]";
|
final boolean | transferAfterCancelledWait(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node node)Transfers node, if necessary, to sync queue after a cancelled
wait. Returns true if thread was cancelled before being
signalled.
if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
enq(node);
return true;
}
/*
* If we lost out to a signal(), then we can't proceed
* until it finishes its enq(). Cancelling during an
* incomplete transfer is both rare and transient, so just
* spin.
*/
while (!isOnSyncQueue(node))
Thread.yield();
return false;
|
final boolean | transferForSignal(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node node)Transfers a node from a condition queue onto sync queue.
Returns true if successful.
/*
* If cannot change waitStatus, the node has been cancelled.
*/
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
/*
* Splice onto queue and try to set waitStatus of predecessor to
* indicate that thread is (probably) waiting. If cancelled or
* attempt to set waitStatus fails, wake up to resync (in which
* case the waitStatus can be transiently and harmlessly wrong).
*/
Node p = enq(node);
int c = p.waitStatus;
if (c > 0 || !compareAndSetWaitStatus(p, c, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
|
protected boolean | tryAcquire(long arg)Attempts to acquire in exclusive mode. This method should query
if the state of the object permits it to be acquired in the
exclusive mode, and if so to acquire it.
This method is always invoked by the thread performing
acquire. If this method reports failure, the acquire method
may queue the thread, if it is not already queued, until it is
signalled by a release from some other thread. This can be used
to implement method {@link Lock#tryLock()}.
The default
implementation throws {@link UnsupportedOperationException}.
throw new UnsupportedOperationException();
|
public final boolean | tryAcquireNanos(long arg, long nanosTimeout)Attempts to acquire in exclusive mode, aborting if interrupted,
and failing if the given timeout elapses. Implemented by first
checking interrupt status, then invoking at least once {@link
#tryAcquire}, returning on success. Otherwise, the thread is
queued, possibly repeatedly blocking and unblocking, invoking
{@link #tryAcquire} until success or the thread is interrupted
or the timeout elapses. This method can be used to implement
method {@link Lock#tryLock(long, TimeUnit)}.
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquire(arg) ||
doAcquireNanos(arg, nanosTimeout);
|
protected long | tryAcquireShared(long arg)Attempts to acquire in shared mode. This method should query if
the state of the object permits it to be acquired in the shared
mode, and if so to acquire it.
This method is always invoked by the thread performing
acquire. If this method reports failure, the acquire method
may queue the thread, if it is not already queued, until it is
signalled by a release from some other thread.
The default implementation throws {@link
UnsupportedOperationException}.
throw new UnsupportedOperationException();
|
public final boolean | tryAcquireSharedNanos(long arg, long nanosTimeout)Attempts to acquire in shared mode, aborting if interrupted, and
failing if the given timeout elapses. Implemented by first
checking interrupt status, then invoking at least once {@link
#tryAcquireShared}, returning on success. Otherwise, the
thread is queued, possibly repeatedly blocking and unblocking,
invoking {@link #tryAcquireShared} until success or the thread
is interrupted or the timeout elapses.
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquireShared(arg) >= 0 ||
doAcquireSharedNanos(arg, nanosTimeout);
|
protected boolean | tryRelease(long arg)Attempts to set the state to reflect a release in exclusive
mode.
This method is always invoked by the thread performing release.
The default implementation throws
{@link UnsupportedOperationException}.
throw new UnsupportedOperationException();
|
protected boolean | tryReleaseShared(long arg)Attempts to set the state to reflect a release in shared mode.
This method is always invoked by the thread performing release.
The default implementation throws
{@link UnsupportedOperationException}.
throw new UnsupportedOperationException();
|
private void | unparkSuccessor(java.util.concurrent.locks.AbstractQueuedLongSynchronizer$Node node)Wakes up node's successor, if one exists.
/*
* Try to clear status in anticipation of signalling. It is
* OK if this fails or if status is changed by waiting thread.
*/
compareAndSetWaitStatus(node, Node.SIGNAL, 0);
/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
|