mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8187443: Forest Consolidation: Move files to unified layout
Reviewed-by: darcy, ihse
This commit is contained in:
parent
270fe13182
commit
3789983e89
56923 changed files with 3 additions and 15727 deletions
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.locks;
|
||||
|
||||
/**
|
||||
* A synchronizer that may be exclusively owned by a thread. This
|
||||
* class provides a basis for creating locks and related synchronizers
|
||||
* that may entail a notion of ownership. The
|
||||
* {@code AbstractOwnableSynchronizer} class itself does not manage or
|
||||
* use this information. However, subclasses and tools may use
|
||||
* appropriately maintained values to help control and monitor access
|
||||
* and provide diagnostics.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public abstract class AbstractOwnableSynchronizer
|
||||
implements java.io.Serializable {
|
||||
|
||||
/** Use serial ID even though all fields transient. */
|
||||
private static final long serialVersionUID = 3737899427754241961L;
|
||||
|
||||
/**
|
||||
* Empty constructor for use by subclasses.
|
||||
*/
|
||||
protected AbstractOwnableSynchronizer() { }
|
||||
|
||||
/**
|
||||
* The current owner of exclusive mode synchronization.
|
||||
*/
|
||||
private transient Thread exclusiveOwnerThread;
|
||||
|
||||
/**
|
||||
* Sets the thread that currently owns exclusive access.
|
||||
* A {@code null} argument indicates that no thread owns access.
|
||||
* This method does not otherwise impose any synchronization or
|
||||
* {@code volatile} field accesses.
|
||||
* @param thread the owner thread
|
||||
*/
|
||||
protected final void setExclusiveOwnerThread(Thread thread) {
|
||||
exclusiveOwnerThread = thread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thread last set by {@code setExclusiveOwnerThread},
|
||||
* or {@code null} if never set. This method does not otherwise
|
||||
* impose any synchronization or {@code volatile} field accesses.
|
||||
* @return the owner thread
|
||||
*/
|
||||
protected final Thread getExclusiveOwnerThread() {
|
||||
return exclusiveOwnerThread;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,486 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.locks;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* {@code Condition} factors out the {@code Object} monitor
|
||||
* methods ({@link Object#wait() wait}, {@link Object#notify notify}
|
||||
* and {@link Object#notifyAll notifyAll}) into distinct objects to
|
||||
* give the effect of having multiple wait-sets per object, by
|
||||
* combining them with the use of arbitrary {@link Lock} implementations.
|
||||
* Where a {@code Lock} replaces the use of {@code synchronized} methods
|
||||
* and statements, a {@code Condition} replaces the use of the Object
|
||||
* monitor methods.
|
||||
*
|
||||
* <p>Conditions (also known as <em>condition queues</em> or
|
||||
* <em>condition variables</em>) provide a means for one thread to
|
||||
* suspend execution (to "wait") until notified by another
|
||||
* thread that some state condition may now be true. Because access
|
||||
* to this shared state information occurs in different threads, it
|
||||
* must be protected, so a lock of some form is associated with the
|
||||
* condition. The key property that waiting for a condition provides
|
||||
* is that it <em>atomically</em> releases the associated lock and
|
||||
* suspends the current thread, just like {@code Object.wait}.
|
||||
*
|
||||
* <p>A {@code Condition} instance is intrinsically bound to a lock.
|
||||
* To obtain a {@code Condition} instance for a particular {@link Lock}
|
||||
* instance use its {@link Lock#newCondition newCondition()} method.
|
||||
*
|
||||
* <p>As an example, suppose we have a bounded buffer which supports
|
||||
* {@code put} and {@code take} methods. If a
|
||||
* {@code take} is attempted on an empty buffer, then the thread will block
|
||||
* until an item becomes available; if a {@code put} is attempted on a
|
||||
* full buffer, then the thread will block until a space becomes available.
|
||||
* We would like to keep waiting {@code put} threads and {@code take}
|
||||
* threads in separate wait-sets so that we can use the optimization of
|
||||
* only notifying a single thread at a time when items or spaces become
|
||||
* available in the buffer. This can be achieved using two
|
||||
* {@link Condition} instances.
|
||||
* <pre>
|
||||
* class BoundedBuffer {
|
||||
* <b>final Lock lock = new ReentrantLock();</b>
|
||||
* final Condition notFull = <b>lock.newCondition(); </b>
|
||||
* final Condition notEmpty = <b>lock.newCondition(); </b>
|
||||
*
|
||||
* final Object[] items = new Object[100];
|
||||
* int putptr, takeptr, count;
|
||||
*
|
||||
* public void put(Object x) throws InterruptedException {
|
||||
* <b>lock.lock();
|
||||
* try {</b>
|
||||
* while (count == items.length)
|
||||
* <b>notFull.await();</b>
|
||||
* items[putptr] = x;
|
||||
* if (++putptr == items.length) putptr = 0;
|
||||
* ++count;
|
||||
* <b>notEmpty.signal();</b>
|
||||
* <b>} finally {
|
||||
* lock.unlock();
|
||||
* }</b>
|
||||
* }
|
||||
*
|
||||
* public Object take() throws InterruptedException {
|
||||
* <b>lock.lock();
|
||||
* try {</b>
|
||||
* while (count == 0)
|
||||
* <b>notEmpty.await();</b>
|
||||
* Object x = items[takeptr];
|
||||
* if (++takeptr == items.length) takeptr = 0;
|
||||
* --count;
|
||||
* <b>notFull.signal();</b>
|
||||
* return x;
|
||||
* <b>} finally {
|
||||
* lock.unlock();
|
||||
* }</b>
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* (The {@link java.util.concurrent.ArrayBlockingQueue} class provides
|
||||
* this functionality, so there is no reason to implement this
|
||||
* sample usage class.)
|
||||
*
|
||||
* <p>A {@code Condition} implementation can provide behavior and semantics
|
||||
* that is
|
||||
* different from that of the {@code Object} monitor methods, such as
|
||||
* guaranteed ordering for notifications, or not requiring a lock to be held
|
||||
* when performing notifications.
|
||||
* If an implementation provides such specialized semantics then the
|
||||
* implementation must document those semantics.
|
||||
*
|
||||
* <p>Note that {@code Condition} instances are just normal objects and can
|
||||
* themselves be used as the target in a {@code synchronized} statement,
|
||||
* and can have their own monitor {@link Object#wait wait} and
|
||||
* {@link Object#notify notify} methods invoked.
|
||||
* Acquiring the monitor lock of a {@code Condition} instance, or using its
|
||||
* monitor methods, has no specified relationship with acquiring the
|
||||
* {@link Lock} associated with that {@code Condition} or the use of its
|
||||
* {@linkplain #await waiting} and {@linkplain #signal signalling} methods.
|
||||
* It is recommended that to avoid confusion you never use {@code Condition}
|
||||
* instances in this way, except perhaps within their own implementation.
|
||||
*
|
||||
* <p>Except where noted, passing a {@code null} value for any parameter
|
||||
* will result in a {@link NullPointerException} being thrown.
|
||||
*
|
||||
* <h3>Implementation Considerations</h3>
|
||||
*
|
||||
* <p>When waiting upon a {@code Condition}, a "<em>spurious
|
||||
* wakeup</em>" is permitted to occur, in
|
||||
* general, as a concession to the underlying platform semantics.
|
||||
* This has little practical impact on most application programs as a
|
||||
* {@code Condition} should always be waited upon in a loop, testing
|
||||
* the state predicate that is being waited for. An implementation is
|
||||
* free to remove the possibility of spurious wakeups but it is
|
||||
* recommended that applications programmers always assume that they can
|
||||
* occur and so always wait in a loop.
|
||||
*
|
||||
* <p>The three forms of condition waiting
|
||||
* (interruptible, non-interruptible, and timed) may differ in their ease of
|
||||
* implementation on some platforms and in their performance characteristics.
|
||||
* In particular, it may be difficult to provide these features and maintain
|
||||
* specific semantics such as ordering guarantees.
|
||||
* Further, the ability to interrupt the actual suspension of the thread may
|
||||
* not always be feasible to implement on all platforms.
|
||||
*
|
||||
* <p>Consequently, an implementation is not required to define exactly the
|
||||
* same guarantees or semantics for all three forms of waiting, nor is it
|
||||
* required to support interruption of the actual suspension of the thread.
|
||||
*
|
||||
* <p>An implementation is required to
|
||||
* clearly document the semantics and guarantees provided by each of the
|
||||
* waiting methods, and when an implementation does support interruption of
|
||||
* thread suspension then it must obey the interruption semantics as defined
|
||||
* in this interface.
|
||||
*
|
||||
* <p>As interruption generally implies cancellation, and checks for
|
||||
* interruption are often infrequent, an implementation can favor responding
|
||||
* to an interrupt over normal method return. This is true even if it can be
|
||||
* shown that the interrupt occurred after another action that may have
|
||||
* unblocked the thread. An implementation should document this behavior.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public interface Condition {
|
||||
|
||||
/**
|
||||
* Causes the current thread to wait until it is signalled or
|
||||
* {@linkplain Thread#interrupt interrupted}.
|
||||
*
|
||||
* <p>The lock associated with this {@code Condition} is atomically
|
||||
* released and the current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until <em>one</em> of four things happens:
|
||||
* <ul>
|
||||
* <li>Some other thread invokes the {@link #signal} method for this
|
||||
* {@code Condition} and the current thread happens to be chosen as the
|
||||
* thread to be awakened; or
|
||||
* <li>Some other thread invokes the {@link #signalAll} method for this
|
||||
* {@code Condition}; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts} the
|
||||
* current thread, and interruption of thread suspension is supported; or
|
||||
* <li>A "<em>spurious wakeup</em>" occurs.
|
||||
* </ul>
|
||||
*
|
||||
* <p>In all cases, before this method can return the current thread must
|
||||
* re-acquire the lock associated with this condition. When the
|
||||
* thread returns it is <em>guaranteed</em> to hold this lock.
|
||||
*
|
||||
* <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 waiting
|
||||
* and interruption of thread suspension is supported,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared. It is not specified, in the first
|
||||
* case, whether or not the test for interruption occurs before the lock
|
||||
* is released.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>The current thread is assumed to hold the lock associated with this
|
||||
* {@code Condition} when this method is called.
|
||||
* It is up to the implementation to determine if this is
|
||||
* the case and if not, how to respond. Typically, an exception will be
|
||||
* thrown (such as {@link IllegalMonitorStateException}) and the
|
||||
* implementation must document that fact.
|
||||
*
|
||||
* <p>An implementation can favor responding to an interrupt over normal
|
||||
* method return in response to a signal. In that case the implementation
|
||||
* must ensure that the signal is redirected to another waiting thread, if
|
||||
* there is one.
|
||||
*
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
* (and interruption of thread suspension is supported)
|
||||
*/
|
||||
void await() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Causes the current thread to wait until it is signalled.
|
||||
*
|
||||
* <p>The lock associated with this condition is atomically
|
||||
* released and the current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until <em>one</em> of three things happens:
|
||||
* <ul>
|
||||
* <li>Some other thread invokes the {@link #signal} method for this
|
||||
* {@code Condition} and the current thread happens to be chosen as the
|
||||
* thread to be awakened; or
|
||||
* <li>Some other thread invokes the {@link #signalAll} method for this
|
||||
* {@code Condition}; or
|
||||
* <li>A "<em>spurious wakeup</em>" occurs.
|
||||
* </ul>
|
||||
*
|
||||
* <p>In all cases, before this method can return the current thread must
|
||||
* re-acquire the lock associated with this condition. When the
|
||||
* thread returns it is <em>guaranteed</em> to hold this lock.
|
||||
*
|
||||
* <p>If the current thread's interrupted status is set when it enters
|
||||
* this method, or it is {@linkplain Thread#interrupt interrupted}
|
||||
* while waiting, it will continue to wait until signalled. When it finally
|
||||
* returns from this method its interrupted status will still
|
||||
* be set.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>The current thread is assumed to hold the lock associated with this
|
||||
* {@code Condition} when this method is called.
|
||||
* It is up to the implementation to determine if this is
|
||||
* the case and if not, how to respond. Typically, an exception will be
|
||||
* thrown (such as {@link IllegalMonitorStateException}) and the
|
||||
* implementation must document that fact.
|
||||
*/
|
||||
void awaitUninterruptibly();
|
||||
|
||||
/**
|
||||
* Causes the current thread to wait until it is signalled or interrupted,
|
||||
* or the specified waiting time elapses.
|
||||
*
|
||||
* <p>The lock associated with this condition is atomically
|
||||
* released and the current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until <em>one</em> of five things happens:
|
||||
* <ul>
|
||||
* <li>Some other thread invokes the {@link #signal} method for this
|
||||
* {@code Condition} and the current thread happens to be chosen as the
|
||||
* thread to be awakened; or
|
||||
* <li>Some other thread invokes the {@link #signalAll} method for this
|
||||
* {@code Condition}; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts} the
|
||||
* current thread, and interruption of thread suspension is supported; or
|
||||
* <li>The specified waiting time elapses; or
|
||||
* <li>A "<em>spurious wakeup</em>" occurs.
|
||||
* </ul>
|
||||
*
|
||||
* <p>In all cases, before this method can return the current thread must
|
||||
* re-acquire the lock associated with this condition. When the
|
||||
* thread returns it is <em>guaranteed</em> to hold this lock.
|
||||
*
|
||||
* <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 waiting
|
||||
* and interruption of thread suspension is supported,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared. It is not specified, in the first
|
||||
* case, whether or not the test for interruption occurs before the lock
|
||||
* is released.
|
||||
*
|
||||
* <p>The method returns an estimate of the number of nanoseconds
|
||||
* remaining to wait given the supplied {@code nanosTimeout}
|
||||
* value upon return, or a value less than or equal to zero if it
|
||||
* timed out. This value can be used to determine whether and how
|
||||
* long to re-wait in cases where the wait returns but an awaited
|
||||
* condition still does not hold. Typical uses of this method take
|
||||
* the following form:
|
||||
*
|
||||
* <pre> {@code
|
||||
* boolean aMethod(long timeout, TimeUnit unit) {
|
||||
* long nanos = unit.toNanos(timeout);
|
||||
* lock.lock();
|
||||
* try {
|
||||
* while (!conditionBeingWaitedFor()) {
|
||||
* if (nanos <= 0L)
|
||||
* return false;
|
||||
* nanos = theCondition.awaitNanos(nanos);
|
||||
* }
|
||||
* // ...
|
||||
* } finally {
|
||||
* lock.unlock();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>Design note: This method requires a nanosecond argument so
|
||||
* as to avoid truncation errors in reporting remaining times.
|
||||
* Such precision loss would make it difficult for programmers to
|
||||
* ensure that total waiting times are not systematically shorter
|
||||
* than specified when re-waits occur.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>The current thread is assumed to hold the lock associated with this
|
||||
* {@code Condition} when this method is called.
|
||||
* It is up to the implementation to determine if this is
|
||||
* the case and if not, how to respond. Typically, an exception will be
|
||||
* thrown (such as {@link IllegalMonitorStateException}) and the
|
||||
* implementation must document that fact.
|
||||
*
|
||||
* <p>An implementation can favor responding to an interrupt over normal
|
||||
* method return in response to a signal, or over indicating the elapse
|
||||
* of the specified waiting time. In either case the implementation
|
||||
* must ensure that the signal is redirected to another waiting thread, if
|
||||
* there is one.
|
||||
*
|
||||
* @param nanosTimeout the maximum time to wait, in nanoseconds
|
||||
* @return an estimate of the {@code nanosTimeout} value minus
|
||||
* the time spent waiting upon return from this method.
|
||||
* A positive value may be used as the argument to a
|
||||
* subsequent call to this method to finish waiting out
|
||||
* the desired time. A value less than or equal to zero
|
||||
* indicates that no time remains.
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
* (and interruption of thread suspension is supported)
|
||||
*/
|
||||
long awaitNanos(long nanosTimeout) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Causes the current thread to wait until it is signalled or interrupted,
|
||||
* or the specified waiting time elapses. This method is behaviorally
|
||||
* equivalent to:
|
||||
* <pre> {@code awaitNanos(unit.toNanos(time)) > 0}</pre>
|
||||
*
|
||||
* @param time the maximum time to wait
|
||||
* @param unit the time unit of the {@code time} argument
|
||||
* @return {@code false} if the waiting time detectably elapsed
|
||||
* before return from the method, else {@code true}
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
* (and interruption of thread suspension is supported)
|
||||
*/
|
||||
boolean await(long time, TimeUnit unit) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Causes the current thread to wait until it is signalled or interrupted,
|
||||
* or the specified deadline elapses.
|
||||
*
|
||||
* <p>The lock associated with this condition is atomically
|
||||
* released and the current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until <em>one</em> of five things happens:
|
||||
* <ul>
|
||||
* <li>Some other thread invokes the {@link #signal} method for this
|
||||
* {@code Condition} and the current thread happens to be chosen as the
|
||||
* thread to be awakened; or
|
||||
* <li>Some other thread invokes the {@link #signalAll} method for this
|
||||
* {@code Condition}; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts} the
|
||||
* current thread, and interruption of thread suspension is supported; or
|
||||
* <li>The specified deadline elapses; or
|
||||
* <li>A "<em>spurious wakeup</em>" occurs.
|
||||
* </ul>
|
||||
*
|
||||
* <p>In all cases, before this method can return the current thread must
|
||||
* re-acquire the lock associated with this condition. When the
|
||||
* thread returns it is <em>guaranteed</em> to hold this lock.
|
||||
*
|
||||
* <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 waiting
|
||||
* and interruption of thread suspension is supported,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared. It is not specified, in the first
|
||||
* case, whether or not the test for interruption occurs before the lock
|
||||
* is released.
|
||||
*
|
||||
* <p>The return value indicates whether the deadline has elapsed,
|
||||
* which can be used as follows:
|
||||
* <pre> {@code
|
||||
* boolean aMethod(Date deadline) {
|
||||
* boolean stillWaiting = true;
|
||||
* lock.lock();
|
||||
* try {
|
||||
* while (!conditionBeingWaitedFor()) {
|
||||
* if (!stillWaiting)
|
||||
* return false;
|
||||
* stillWaiting = theCondition.awaitUntil(deadline);
|
||||
* }
|
||||
* // ...
|
||||
* } finally {
|
||||
* lock.unlock();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>The current thread is assumed to hold the lock associated with this
|
||||
* {@code Condition} when this method is called.
|
||||
* It is up to the implementation to determine if this is
|
||||
* the case and if not, how to respond. Typically, an exception will be
|
||||
* thrown (such as {@link IllegalMonitorStateException}) and the
|
||||
* implementation must document that fact.
|
||||
*
|
||||
* <p>An implementation can favor responding to an interrupt over normal
|
||||
* method return in response to a signal, or over indicating the passing
|
||||
* of the specified deadline. In either case the implementation
|
||||
* must ensure that the signal is redirected to another waiting thread, if
|
||||
* there is one.
|
||||
*
|
||||
* @param deadline the absolute time to wait until
|
||||
* @return {@code false} if the deadline has elapsed upon return, else
|
||||
* {@code true}
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
* (and interruption of thread suspension is supported)
|
||||
*/
|
||||
boolean awaitUntil(Date deadline) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Wakes up one waiting thread.
|
||||
*
|
||||
* <p>If any threads are waiting on this condition then one
|
||||
* is selected for waking up. That thread must then re-acquire the
|
||||
* lock before returning from {@code await}.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>An implementation may (and typically does) require that the
|
||||
* current thread hold the lock associated with this {@code
|
||||
* Condition} when this method is called. Implementations must
|
||||
* document this precondition and any actions taken if the lock is
|
||||
* not held. Typically, an exception such as {@link
|
||||
* IllegalMonitorStateException} will be thrown.
|
||||
*/
|
||||
void signal();
|
||||
|
||||
/**
|
||||
* Wakes up all waiting threads.
|
||||
*
|
||||
* <p>If any threads are waiting on this condition then they are
|
||||
* all woken up. Each thread must re-acquire the lock before it can
|
||||
* return from {@code await}.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>An implementation may (and typically does) require that the
|
||||
* current thread hold the lock associated with this {@code
|
||||
* Condition} when this method is called. Implementations must
|
||||
* document this precondition and any actions taken if the lock is
|
||||
* not held. Typically, an exception such as {@link
|
||||
* IllegalMonitorStateException} will be thrown.
|
||||
*/
|
||||
void signalAll();
|
||||
}
|
359
src/java.base/share/classes/java/util/concurrent/locks/Lock.java
Normal file
359
src/java.base/share/classes/java/util/concurrent/locks/Lock.java
Normal file
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.locks;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* {@code Lock} implementations provide more extensive locking
|
||||
* operations than can be obtained using {@code synchronized} methods
|
||||
* and statements. They allow more flexible structuring, may have
|
||||
* quite different properties, and may support multiple associated
|
||||
* {@link Condition} objects.
|
||||
*
|
||||
* <p>A lock is a tool for controlling access to a shared resource by
|
||||
* multiple threads. Commonly, a lock provides exclusive access to a
|
||||
* shared resource: only one thread at a time can acquire the lock and
|
||||
* all access to the shared resource requires that the lock be
|
||||
* acquired first. However, some locks may allow concurrent access to
|
||||
* a shared resource, such as the read lock of a {@link ReadWriteLock}.
|
||||
*
|
||||
* <p>The use of {@code synchronized} methods or statements provides
|
||||
* access to the implicit monitor lock associated with every object, but
|
||||
* forces all lock acquisition and release to occur in a block-structured way:
|
||||
* when multiple locks are acquired they must be released in the opposite
|
||||
* order, and all locks must be released in the same lexical scope in which
|
||||
* they were acquired.
|
||||
*
|
||||
* <p>While the scoping mechanism for {@code synchronized} methods
|
||||
* and statements makes it much easier to program with monitor locks,
|
||||
* and helps avoid many common programming errors involving locks,
|
||||
* there are occasions where you need to work with locks in a more
|
||||
* flexible way. For example, some algorithms for traversing
|
||||
* concurrently accessed data structures require the use of
|
||||
* "hand-over-hand" or "chain locking": you
|
||||
* acquire the lock of node A, then node B, then release A and acquire
|
||||
* C, then release B and acquire D and so on. Implementations of the
|
||||
* {@code Lock} interface enable the use of such techniques by
|
||||
* allowing a lock to be acquired and released in different scopes,
|
||||
* and allowing multiple locks to be acquired and released in any
|
||||
* order.
|
||||
*
|
||||
* <p>With this increased flexibility comes additional
|
||||
* responsibility. The absence of block-structured locking removes the
|
||||
* automatic release of locks that occurs with {@code synchronized}
|
||||
* methods and statements. In most cases, the following idiom
|
||||
* should be used:
|
||||
*
|
||||
* <pre> {@code
|
||||
* Lock l = ...;
|
||||
* l.lock();
|
||||
* try {
|
||||
* // access the resource protected by this lock
|
||||
* } finally {
|
||||
* l.unlock();
|
||||
* }}</pre>
|
||||
*
|
||||
* When locking and unlocking occur in different scopes, care must be
|
||||
* taken to ensure that all code that is executed while the lock is
|
||||
* held is protected by try-finally or try-catch to ensure that the
|
||||
* lock is released when necessary.
|
||||
*
|
||||
* <p>{@code Lock} implementations provide additional functionality
|
||||
* over the use of {@code synchronized} methods and statements by
|
||||
* providing a non-blocking attempt to acquire a lock ({@link
|
||||
* #tryLock()}), an attempt to acquire the lock that can be
|
||||
* interrupted ({@link #lockInterruptibly}, and an attempt to acquire
|
||||
* the lock that can timeout ({@link #tryLock(long, TimeUnit)}).
|
||||
*
|
||||
* <p>A {@code Lock} class can also provide behavior and semantics
|
||||
* that is quite different from that of the implicit monitor lock,
|
||||
* such as guaranteed ordering, non-reentrant usage, or deadlock
|
||||
* detection. If an implementation provides such specialized semantics
|
||||
* then the implementation must document those semantics.
|
||||
*
|
||||
* <p>Note that {@code Lock} instances are just normal objects and can
|
||||
* themselves be used as the target in a {@code synchronized} statement.
|
||||
* Acquiring the
|
||||
* monitor lock of a {@code Lock} instance has no specified relationship
|
||||
* with invoking any of the {@link #lock} methods of that instance.
|
||||
* It is recommended that to avoid confusion you never use {@code Lock}
|
||||
* instances in this way, except within their own implementation.
|
||||
*
|
||||
* <p>Except where noted, passing a {@code null} value for any
|
||||
* parameter will result in a {@link NullPointerException} being
|
||||
* thrown.
|
||||
*
|
||||
* <h3>Memory Synchronization</h3>
|
||||
*
|
||||
* <p>All {@code Lock} implementations <em>must</em> enforce the same
|
||||
* memory synchronization semantics as provided by the built-in monitor
|
||||
* lock, as described in
|
||||
* <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4">
|
||||
* Chapter 17 of
|
||||
* <cite>The Java™ Language Specification</cite></a>:
|
||||
* <ul>
|
||||
* <li>A successful {@code lock} operation has the same memory
|
||||
* synchronization effects as a successful <em>Lock</em> action.
|
||||
* <li>A successful {@code unlock} operation has the same
|
||||
* memory synchronization effects as a successful <em>Unlock</em> action.
|
||||
* </ul>
|
||||
*
|
||||
* Unsuccessful locking and unlocking operations, and reentrant
|
||||
* locking/unlocking operations, do not require any memory
|
||||
* synchronization effects.
|
||||
*
|
||||
* <h3>Implementation Considerations</h3>
|
||||
*
|
||||
* <p>The three forms of lock acquisition (interruptible,
|
||||
* non-interruptible, and timed) may differ in their performance
|
||||
* characteristics, ordering guarantees, or other implementation
|
||||
* qualities. Further, the ability to interrupt the <em>ongoing</em>
|
||||
* acquisition of a lock may not be available in a given {@code Lock}
|
||||
* class. Consequently, an implementation is not required to define
|
||||
* exactly the same guarantees or semantics for all three forms of
|
||||
* lock acquisition, nor is it required to support interruption of an
|
||||
* ongoing lock acquisition. An implementation is required to clearly
|
||||
* document the semantics and guarantees provided by each of the
|
||||
* locking methods. It must also obey the interruption semantics as
|
||||
* defined in this interface, to the extent that interruption of lock
|
||||
* acquisition is supported: which is either totally, or only on
|
||||
* method entry.
|
||||
*
|
||||
* <p>As interruption generally implies cancellation, and checks for
|
||||
* interruption are often infrequent, an implementation can favor responding
|
||||
* to an interrupt over normal method return. This is true even if it can be
|
||||
* shown that the interrupt occurred after another action may have unblocked
|
||||
* the thread. An implementation should document this behavior.
|
||||
*
|
||||
* @see ReentrantLock
|
||||
* @see Condition
|
||||
* @see ReadWriteLock
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public interface Lock {
|
||||
|
||||
/**
|
||||
* Acquires the lock.
|
||||
*
|
||||
* <p>If the lock is not available then the current thread becomes
|
||||
* disabled for thread scheduling purposes and lies dormant until the
|
||||
* lock has been acquired.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>A {@code Lock} implementation may be able to detect erroneous use
|
||||
* of the lock, such as an invocation that would cause deadlock, and
|
||||
* may throw an (unchecked) exception in such circumstances. The
|
||||
* circumstances and the exception type must be documented by that
|
||||
* {@code Lock} implementation.
|
||||
*/
|
||||
void lock();
|
||||
|
||||
/**
|
||||
* Acquires the lock unless the current thread is
|
||||
* {@linkplain Thread#interrupt interrupted}.
|
||||
*
|
||||
* <p>Acquires the lock if it is available and returns immediately.
|
||||
*
|
||||
* <p>If the lock is not available then the current thread becomes
|
||||
* disabled for thread scheduling purposes and lies dormant until
|
||||
* one of two things happens:
|
||||
*
|
||||
* <ul>
|
||||
* <li>The lock is acquired by the current thread; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts} the
|
||||
* current thread, and interruption of lock acquisition is supported.
|
||||
* </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
|
||||
* lock, and interruption of lock acquisition is supported,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>The ability to interrupt a lock acquisition in some
|
||||
* implementations may not be possible, and if possible may be an
|
||||
* expensive operation. The programmer should be aware that this
|
||||
* may be the case. An implementation should document when this is
|
||||
* the case.
|
||||
*
|
||||
* <p>An implementation can favor responding to an interrupt over
|
||||
* normal method return.
|
||||
*
|
||||
* <p>A {@code Lock} implementation may be able to detect
|
||||
* erroneous use of the lock, such as an invocation that would
|
||||
* cause deadlock, and may throw an (unchecked) exception in such
|
||||
* circumstances. The circumstances and the exception type must
|
||||
* be documented by that {@code Lock} implementation.
|
||||
*
|
||||
* @throws InterruptedException if the current thread is
|
||||
* interrupted while acquiring the lock (and interruption
|
||||
* of lock acquisition is supported)
|
||||
*/
|
||||
void lockInterruptibly() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Acquires the lock only if it is free at the time of invocation.
|
||||
*
|
||||
* <p>Acquires the lock if it is available and returns immediately
|
||||
* with the value {@code true}.
|
||||
* If the lock is not available then this method will return
|
||||
* immediately with the value {@code false}.
|
||||
*
|
||||
* <p>A typical usage idiom for this method would be:
|
||||
* <pre> {@code
|
||||
* Lock lock = ...;
|
||||
* if (lock.tryLock()) {
|
||||
* try {
|
||||
* // manipulate protected state
|
||||
* } finally {
|
||||
* lock.unlock();
|
||||
* }
|
||||
* } else {
|
||||
* // perform alternative actions
|
||||
* }}</pre>
|
||||
*
|
||||
* This usage ensures that the lock is unlocked if it was acquired, and
|
||||
* doesn't try to unlock if the lock was not acquired.
|
||||
*
|
||||
* @return {@code true} if the lock was acquired and
|
||||
* {@code false} otherwise
|
||||
*/
|
||||
boolean tryLock();
|
||||
|
||||
/**
|
||||
* Acquires the lock if it is free within the given waiting time and the
|
||||
* current thread has not been {@linkplain Thread#interrupt interrupted}.
|
||||
*
|
||||
* <p>If the lock is available this method returns immediately
|
||||
* with the value {@code true}.
|
||||
* If the lock is not available then
|
||||
* the current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until one of three things happens:
|
||||
* <ul>
|
||||
* <li>The lock is acquired by the current thread; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts} the
|
||||
* current thread, and interruption of lock acquisition is supported; or
|
||||
* <li>The specified waiting time elapses
|
||||
* </ul>
|
||||
*
|
||||
* <p>If the 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 lock, and interruption of lock acquisition is supported,
|
||||
* </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><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>The ability to interrupt a lock acquisition in some implementations
|
||||
* may not be possible, and if possible may
|
||||
* be an expensive operation.
|
||||
* The programmer should be aware that this may be the case. An
|
||||
* implementation should document when this is the case.
|
||||
*
|
||||
* <p>An implementation can favor responding to an interrupt over normal
|
||||
* method return, or reporting a timeout.
|
||||
*
|
||||
* <p>A {@code Lock} implementation may be able to detect
|
||||
* erroneous use of the lock, such as an invocation that would cause
|
||||
* deadlock, and may throw an (unchecked) exception in such circumstances.
|
||||
* The circumstances and the exception type must be documented by that
|
||||
* {@code Lock} implementation.
|
||||
*
|
||||
* @param time the maximum time to wait for the lock
|
||||
* @param unit the time unit of the {@code time} argument
|
||||
* @return {@code true} if the lock was acquired and {@code false}
|
||||
* if the waiting time elapsed before the lock was acquired
|
||||
*
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
* while acquiring the lock (and interruption of lock
|
||||
* acquisition is supported)
|
||||
*/
|
||||
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Releases the lock.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>A {@code Lock} implementation will usually impose
|
||||
* restrictions on which thread can release a lock (typically only the
|
||||
* holder of the lock can release it) and may throw
|
||||
* an (unchecked) exception if the restriction is violated.
|
||||
* Any restrictions and the exception
|
||||
* type must be documented by that {@code Lock} implementation.
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
/**
|
||||
* Returns a new {@link Condition} instance that is bound to this
|
||||
* {@code Lock} instance.
|
||||
*
|
||||
* <p>Before waiting on the condition the lock must be held by the
|
||||
* current thread.
|
||||
* A call to {@link Condition#await()} will atomically release the lock
|
||||
* before waiting and re-acquire the lock before the wait returns.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>The exact operation of the {@link Condition} instance depends on
|
||||
* the {@code Lock} implementation and must be documented by that
|
||||
* implementation.
|
||||
*
|
||||
* @return A new {@link Condition} instance for this {@code Lock} instance
|
||||
* @throws UnsupportedOperationException if this {@code Lock}
|
||||
* implementation does not support conditions
|
||||
*/
|
||||
Condition newCondition();
|
||||
}
|
|
@ -0,0 +1,431 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.locks;
|
||||
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* Basic thread blocking primitives for creating locks and other
|
||||
* synchronization classes.
|
||||
*
|
||||
* <p>This class associates, with each thread that uses it, a permit
|
||||
* (in the sense of the {@link java.util.concurrent.Semaphore
|
||||
* Semaphore} class). A call to {@code park} will return immediately
|
||||
* if the permit is available, consuming it in the process; otherwise
|
||||
* it <em>may</em> block. A call to {@code unpark} makes the permit
|
||||
* available, if it was not already available. (Unlike with Semaphores
|
||||
* though, permits do not accumulate. There is at most one.)
|
||||
* Reliable usage requires the use of volatile (or atomic) variables
|
||||
* to control when to park or unpark. Orderings of calls to these
|
||||
* methods are maintained with respect to volatile variable accesses,
|
||||
* but not necessarily non-volatile variable accesses.
|
||||
*
|
||||
* <p>Methods {@code park} and {@code unpark} provide efficient
|
||||
* means of blocking and unblocking threads that do not encounter the
|
||||
* problems that cause the deprecated methods {@code Thread.suspend}
|
||||
* and {@code Thread.resume} to be unusable for such purposes: Races
|
||||
* between one thread invoking {@code park} and another thread trying
|
||||
* to {@code unpark} it will preserve liveness, due to the
|
||||
* permit. Additionally, {@code park} will return if the caller's
|
||||
* thread was interrupted, and timeout versions are supported. The
|
||||
* {@code park} method may also return at any other time, for "no
|
||||
* reason", so in general must be invoked within a loop that rechecks
|
||||
* conditions upon return. In this sense {@code park} serves as an
|
||||
* optimization of a "busy wait" that does not waste as much time
|
||||
* spinning, but must be paired with an {@code unpark} to be
|
||||
* effective.
|
||||
*
|
||||
* <p>The three forms of {@code park} each also support a
|
||||
* {@code blocker} object parameter. This object is recorded while
|
||||
* the thread is blocked to permit monitoring and diagnostic tools to
|
||||
* identify the reasons that threads are blocked. (Such tools may
|
||||
* access blockers using method {@link #getBlocker(Thread)}.)
|
||||
* The use of these forms rather than the original forms without this
|
||||
* parameter is strongly encouraged. The normal argument to supply as
|
||||
* a {@code blocker} within a lock implementation is {@code this}.
|
||||
*
|
||||
* <p>These methods are designed to be used as tools for creating
|
||||
* higher-level synchronization utilities, and are not in themselves
|
||||
* useful for most concurrency control applications. The {@code park}
|
||||
* method is designed for use only in constructions of the form:
|
||||
*
|
||||
* <pre> {@code
|
||||
* while (!canProceed()) {
|
||||
* // ensure request to unpark is visible to other threads
|
||||
* ...
|
||||
* LockSupport.park(this);
|
||||
* }}</pre>
|
||||
*
|
||||
* where no actions by the thread publishing a request to unpark,
|
||||
* prior to the call to {@code park}, entail locking or blocking.
|
||||
* Because only one permit is associated with each thread, any
|
||||
* intermediary uses of {@code park}, including implicitly via class
|
||||
* loading, could lead to an unresponsive thread (a "lost unpark").
|
||||
*
|
||||
* <p><b>Sample Usage.</b> Here is a sketch of a first-in-first-out
|
||||
* non-reentrant lock class:
|
||||
* <pre> {@code
|
||||
* class FIFOMutex {
|
||||
* private final AtomicBoolean locked = new AtomicBoolean(false);
|
||||
* private final Queue<Thread> waiters
|
||||
* = new ConcurrentLinkedQueue<>();
|
||||
*
|
||||
* public void lock() {
|
||||
* boolean wasInterrupted = false;
|
||||
* // publish current thread for unparkers
|
||||
* waiters.add(Thread.currentThread());
|
||||
*
|
||||
* // Block while not first in queue or cannot acquire lock
|
||||
* while (waiters.peek() != Thread.currentThread() ||
|
||||
* !locked.compareAndSet(false, true)) {
|
||||
* LockSupport.park(this);
|
||||
* // ignore interrupts while waiting
|
||||
* if (Thread.interrupted())
|
||||
* wasInterrupted = true;
|
||||
* }
|
||||
*
|
||||
* waiters.remove();
|
||||
* // ensure correct interrupt status on return
|
||||
* if (wasInterrupted)
|
||||
* Thread.currentThread().interrupt();
|
||||
* }
|
||||
*
|
||||
* public void unlock() {
|
||||
* locked.set(false);
|
||||
* LockSupport.unpark(waiters.peek());
|
||||
* }
|
||||
*
|
||||
* static {
|
||||
* // Reduce the risk of "lost unpark" due to classloading
|
||||
* Class<?> ensureLoaded = LockSupport.class;
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public class LockSupport {
|
||||
private LockSupport() {} // Cannot be instantiated.
|
||||
|
||||
private static void setBlocker(Thread t, Object arg) {
|
||||
// Even though volatile, hotspot doesn't need a write barrier here.
|
||||
U.putObject(t, PARKBLOCKER, arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes available the permit for the given thread, if it
|
||||
* was not already available. If the thread was blocked on
|
||||
* {@code park} then it will unblock. Otherwise, its next call
|
||||
* to {@code park} is guaranteed not to block. This operation
|
||||
* is not guaranteed to have any effect at all if the given
|
||||
* thread has not been started.
|
||||
*
|
||||
* @param thread the thread to unpark, or {@code null}, in which case
|
||||
* this operation has no effect
|
||||
*/
|
||||
public static void unpark(Thread thread) {
|
||||
if (thread != null)
|
||||
U.unpark(thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the current thread for thread scheduling purposes unless the
|
||||
* permit is available.
|
||||
*
|
||||
* <p>If the permit is available then it is consumed and the call returns
|
||||
* immediately; otherwise
|
||||
* the current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until one of three things happens:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Some other thread invokes {@link #unpark unpark} with the
|
||||
* current thread as the target; or
|
||||
*
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
*
|
||||
* <li>The call spuriously (that is, for no reason) returns.
|
||||
* </ul>
|
||||
*
|
||||
* <p>This method does <em>not</em> report which of these caused the
|
||||
* method to return. Callers should re-check the conditions which caused
|
||||
* the thread to park in the first place. Callers may also determine,
|
||||
* for example, the interrupt status of the thread upon return.
|
||||
*
|
||||
* @param blocker the synchronization object responsible for this
|
||||
* thread parking
|
||||
* @since 1.6
|
||||
*/
|
||||
public static void park(Object blocker) {
|
||||
Thread t = Thread.currentThread();
|
||||
setBlocker(t, blocker);
|
||||
U.park(false, 0L);
|
||||
setBlocker(t, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the current thread for thread scheduling purposes, for up to
|
||||
* the specified waiting time, unless the permit is available.
|
||||
*
|
||||
* <p>If the permit is available then it is consumed and the call
|
||||
* returns immediately; otherwise the current thread becomes disabled
|
||||
* for thread scheduling purposes and lies dormant until one of four
|
||||
* things happens:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Some other thread invokes {@link #unpark unpark} with the
|
||||
* current thread as the target; or
|
||||
*
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
*
|
||||
* <li>The specified waiting time elapses; or
|
||||
*
|
||||
* <li>The call spuriously (that is, for no reason) returns.
|
||||
* </ul>
|
||||
*
|
||||
* <p>This method does <em>not</em> report which of these caused the
|
||||
* method to return. Callers should re-check the conditions which caused
|
||||
* the thread to park in the first place. Callers may also determine,
|
||||
* for example, the interrupt status of the thread, or the elapsed time
|
||||
* upon return.
|
||||
*
|
||||
* @param blocker the synchronization object responsible for this
|
||||
* thread parking
|
||||
* @param nanos the maximum number of nanoseconds to wait
|
||||
* @since 1.6
|
||||
*/
|
||||
public static void parkNanos(Object blocker, long nanos) {
|
||||
if (nanos > 0) {
|
||||
Thread t = Thread.currentThread();
|
||||
setBlocker(t, blocker);
|
||||
U.park(false, nanos);
|
||||
setBlocker(t, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the current thread for thread scheduling purposes, until
|
||||
* the specified deadline, unless the permit is available.
|
||||
*
|
||||
* <p>If the permit is available then it is consumed and the call
|
||||
* returns immediately; otherwise the current thread becomes disabled
|
||||
* for thread scheduling purposes and lies dormant until one of four
|
||||
* things happens:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Some other thread invokes {@link #unpark unpark} with the
|
||||
* current thread as the target; or
|
||||
*
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts} the
|
||||
* current thread; or
|
||||
*
|
||||
* <li>The specified deadline passes; or
|
||||
*
|
||||
* <li>The call spuriously (that is, for no reason) returns.
|
||||
* </ul>
|
||||
*
|
||||
* <p>This method does <em>not</em> report which of these caused the
|
||||
* method to return. Callers should re-check the conditions which caused
|
||||
* the thread to park in the first place. Callers may also determine,
|
||||
* for example, the interrupt status of the thread, or the current time
|
||||
* upon return.
|
||||
*
|
||||
* @param blocker the synchronization object responsible for this
|
||||
* thread parking
|
||||
* @param deadline the absolute time, in milliseconds from the Epoch,
|
||||
* to wait until
|
||||
* @since 1.6
|
||||
*/
|
||||
public static void parkUntil(Object blocker, long deadline) {
|
||||
Thread t = Thread.currentThread();
|
||||
setBlocker(t, blocker);
|
||||
U.park(true, deadline);
|
||||
setBlocker(t, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blocker object supplied to the most recent
|
||||
* invocation of a park method that has not yet unblocked, or null
|
||||
* if not blocked. The value returned is just a momentary
|
||||
* snapshot -- the thread may have since unblocked or blocked on a
|
||||
* different blocker object.
|
||||
*
|
||||
* @param t the thread
|
||||
* @return the blocker
|
||||
* @throws NullPointerException if argument is null
|
||||
* @since 1.6
|
||||
*/
|
||||
public static Object getBlocker(Thread t) {
|
||||
if (t == null)
|
||||
throw new NullPointerException();
|
||||
return U.getObjectVolatile(t, PARKBLOCKER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the current thread for thread scheduling purposes unless the
|
||||
* permit is available.
|
||||
*
|
||||
* <p>If the permit is available then it is consumed and the call
|
||||
* returns immediately; otherwise the current thread becomes disabled
|
||||
* for thread scheduling purposes and lies dormant until one of three
|
||||
* things happens:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li>Some other thread invokes {@link #unpark unpark} with the
|
||||
* current thread as the target; or
|
||||
*
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
*
|
||||
* <li>The call spuriously (that is, for no reason) returns.
|
||||
* </ul>
|
||||
*
|
||||
* <p>This method does <em>not</em> report which of these caused the
|
||||
* method to return. Callers should re-check the conditions which caused
|
||||
* the thread to park in the first place. Callers may also determine,
|
||||
* for example, the interrupt status of the thread upon return.
|
||||
*/
|
||||
public static void park() {
|
||||
U.park(false, 0L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the current thread for thread scheduling purposes, for up to
|
||||
* the specified waiting time, unless the permit is available.
|
||||
*
|
||||
* <p>If the permit is available then it is consumed and the call
|
||||
* returns immediately; otherwise the current thread becomes disabled
|
||||
* for thread scheduling purposes and lies dormant until one of four
|
||||
* things happens:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Some other thread invokes {@link #unpark unpark} with the
|
||||
* current thread as the target; or
|
||||
*
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
*
|
||||
* <li>The specified waiting time elapses; or
|
||||
*
|
||||
* <li>The call spuriously (that is, for no reason) returns.
|
||||
* </ul>
|
||||
*
|
||||
* <p>This method does <em>not</em> report which of these caused the
|
||||
* method to return. Callers should re-check the conditions which caused
|
||||
* the thread to park in the first place. Callers may also determine,
|
||||
* for example, the interrupt status of the thread, or the elapsed time
|
||||
* upon return.
|
||||
*
|
||||
* @param nanos the maximum number of nanoseconds to wait
|
||||
*/
|
||||
public static void parkNanos(long nanos) {
|
||||
if (nanos > 0)
|
||||
U.park(false, nanos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the current thread for thread scheduling purposes, until
|
||||
* the specified deadline, unless the permit is available.
|
||||
*
|
||||
* <p>If the permit is available then it is consumed and the call
|
||||
* returns immediately; otherwise the current thread becomes disabled
|
||||
* for thread scheduling purposes and lies dormant until one of four
|
||||
* things happens:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Some other thread invokes {@link #unpark unpark} with the
|
||||
* current thread as the target; or
|
||||
*
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
*
|
||||
* <li>The specified deadline passes; or
|
||||
*
|
||||
* <li>The call spuriously (that is, for no reason) returns.
|
||||
* </ul>
|
||||
*
|
||||
* <p>This method does <em>not</em> report which of these caused the
|
||||
* method to return. Callers should re-check the conditions which caused
|
||||
* the thread to park in the first place. Callers may also determine,
|
||||
* for example, the interrupt status of the thread, or the current time
|
||||
* upon return.
|
||||
*
|
||||
* @param deadline the absolute time, in milliseconds from the Epoch,
|
||||
* to wait until
|
||||
*/
|
||||
public static void parkUntil(long deadline) {
|
||||
U.park(true, deadline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pseudo-randomly initialized or updated secondary seed.
|
||||
* Copied from ThreadLocalRandom due to package access restrictions.
|
||||
*/
|
||||
static final int nextSecondarySeed() {
|
||||
int r;
|
||||
Thread t = Thread.currentThread();
|
||||
if ((r = U.getInt(t, SECONDARY)) != 0) {
|
||||
r ^= r << 13; // xorshift
|
||||
r ^= r >>> 17;
|
||||
r ^= r << 5;
|
||||
}
|
||||
else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0)
|
||||
r = 1; // avoid zero
|
||||
U.putInt(t, SECONDARY, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thread id for the given thread. We must access
|
||||
* this directly rather than via method Thread.getId() because
|
||||
* getId() is not final, and has been known to be overridden in
|
||||
* ways that do not preserve unique mappings.
|
||||
*/
|
||||
static final long getThreadId(Thread thread) {
|
||||
return U.getLongVolatile(thread, TID);
|
||||
}
|
||||
|
||||
// Hotspot implementation via intrinsics API
|
||||
private static final Unsafe U = Unsafe.getUnsafe();
|
||||
private static final long PARKBLOCKER = U.objectFieldOffset
|
||||
(Thread.class, "parkBlocker");
|
||||
private static final long SECONDARY = U.objectFieldOffset
|
||||
(Thread.class, "threadLocalRandomSecondarySeed");
|
||||
private static final long TID = U.objectFieldOffset
|
||||
(Thread.class, "tid");
|
||||
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.locks;
|
||||
|
||||
/**
|
||||
* A {@code ReadWriteLock} maintains a pair of associated {@link
|
||||
* Lock locks}, one for read-only operations and one for writing.
|
||||
* The {@linkplain #readLock read lock} may be held simultaneously
|
||||
* by multiple reader threads, so long as there are no writers.
|
||||
* The {@linkplain #writeLock write lock} is exclusive.
|
||||
*
|
||||
* <p>All {@code ReadWriteLock} implementations must guarantee that
|
||||
* the memory synchronization effects of {@code writeLock} operations
|
||||
* (as specified in the {@link Lock} interface) also hold with respect
|
||||
* to the associated {@code readLock}. That is, a thread successfully
|
||||
* acquiring the read lock will see all updates made upon previous
|
||||
* release of the write lock.
|
||||
*
|
||||
* <p>A read-write lock allows for a greater level of concurrency in
|
||||
* accessing shared data than that permitted by a mutual exclusion lock.
|
||||
* It exploits the fact that while only a single thread at a time (a
|
||||
* <em>writer</em> thread) can modify the shared data, in many cases any
|
||||
* number of threads can concurrently read the data (hence <em>reader</em>
|
||||
* threads).
|
||||
* In theory, the increase in concurrency permitted by the use of a read-write
|
||||
* lock will lead to performance improvements over the use of a mutual
|
||||
* exclusion lock. In practice this increase in concurrency will only be fully
|
||||
* realized on a multi-processor, and then only if the access patterns for
|
||||
* the shared data are suitable.
|
||||
*
|
||||
* <p>Whether or not a read-write lock will improve performance over the use
|
||||
* of a mutual exclusion lock depends on the frequency that the data is
|
||||
* read compared to being modified, the duration of the read and write
|
||||
* operations, and the contention for the data - that is, the number of
|
||||
* threads that will try to read or write the data at the same time.
|
||||
* For example, a collection that is initially populated with data and
|
||||
* thereafter infrequently modified, while being frequently searched
|
||||
* (such as a directory of some kind) is an ideal candidate for the use of
|
||||
* a read-write lock. However, if updates become frequent then the data
|
||||
* spends most of its time being exclusively locked and there is little, if any
|
||||
* increase in concurrency. Further, if the read operations are too short
|
||||
* the overhead of the read-write lock implementation (which is inherently
|
||||
* more complex than a mutual exclusion lock) can dominate the execution
|
||||
* cost, particularly as many read-write lock implementations still serialize
|
||||
* all threads through a small section of code. Ultimately, only profiling
|
||||
* and measurement will establish whether the use of a read-write lock is
|
||||
* suitable for your application.
|
||||
*
|
||||
* <p>Although the basic operation of a read-write lock is straight-forward,
|
||||
* there are many policy decisions that an implementation must make, which
|
||||
* may affect the effectiveness of the read-write lock in a given application.
|
||||
* Examples of these policies include:
|
||||
* <ul>
|
||||
* <li>Determining whether to grant the read lock or the write lock, when
|
||||
* both readers and writers are waiting, at the time that a writer releases
|
||||
* the write lock. Writer preference is common, as writes are expected to be
|
||||
* short and infrequent. Reader preference is less common as it can lead to
|
||||
* lengthy delays for a write if the readers are frequent and long-lived as
|
||||
* expected. Fair, or "in-order" implementations are also possible.
|
||||
*
|
||||
* <li>Determining whether readers that request the read lock while a
|
||||
* reader is active and a writer is waiting, are granted the read lock.
|
||||
* Preference to the reader can delay the writer indefinitely, while
|
||||
* preference to the writer can reduce the potential for concurrency.
|
||||
*
|
||||
* <li>Determining whether the locks are reentrant: can a thread with the
|
||||
* write lock reacquire it? Can it acquire a read lock while holding the
|
||||
* write lock? Is the read lock itself reentrant?
|
||||
*
|
||||
* <li>Can the write lock be downgraded to a read lock without allowing
|
||||
* an intervening writer? Can a read lock be upgraded to a write lock,
|
||||
* in preference to other waiting readers or writers?
|
||||
*
|
||||
* </ul>
|
||||
* You should consider all of these things when evaluating the suitability
|
||||
* of a given implementation for your application.
|
||||
*
|
||||
* @see ReentrantReadWriteLock
|
||||
* @see Lock
|
||||
* @see ReentrantLock
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public interface ReadWriteLock {
|
||||
/**
|
||||
* Returns the lock used for reading.
|
||||
*
|
||||
* @return the lock used for reading
|
||||
*/
|
||||
Lock readLock();
|
||||
|
||||
/**
|
||||
* Returns the lock used for writing.
|
||||
*
|
||||
* @return the lock used for writing
|
||||
*/
|
||||
Lock writeLock();
|
||||
}
|
|
@ -0,0 +1,743 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.locks;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import jdk.internal.vm.annotation.ReservedStackAccess;
|
||||
|
||||
/**
|
||||
* A reentrant mutual exclusion {@link Lock} with the same basic
|
||||
* behavior and semantics as the implicit monitor lock accessed using
|
||||
* {@code synchronized} methods and statements, but with extended
|
||||
* capabilities.
|
||||
*
|
||||
* <p>A {@code ReentrantLock} is <em>owned</em> by the thread last
|
||||
* successfully locking, but not yet unlocking it. A thread invoking
|
||||
* {@code lock} will return, successfully acquiring the lock, when
|
||||
* the lock is not owned by another thread. The method will return
|
||||
* immediately if the current thread already owns the lock. This can
|
||||
* be checked using methods {@link #isHeldByCurrentThread}, and {@link
|
||||
* #getHoldCount}.
|
||||
*
|
||||
* <p>The constructor for this class accepts an optional
|
||||
* <em>fairness</em> parameter. When set {@code true}, under
|
||||
* contention, locks favor granting access to the longest-waiting
|
||||
* thread. Otherwise this lock does not guarantee any particular
|
||||
* access order. Programs using fair locks accessed by many threads
|
||||
* may display lower overall throughput (i.e., are slower; often much
|
||||
* slower) than those using the default setting, but have smaller
|
||||
* variances in times to obtain locks and guarantee lack of
|
||||
* starvation. Note however, that fairness of locks does not guarantee
|
||||
* fairness of thread scheduling. Thus, one of many threads using a
|
||||
* fair lock may obtain it multiple times in succession while other
|
||||
* active threads are not progressing and not currently holding the
|
||||
* lock.
|
||||
* Also note that the untimed {@link #tryLock()} method does not
|
||||
* honor the fairness setting. It will succeed if the lock
|
||||
* is available even if other threads are waiting.
|
||||
*
|
||||
* <p>It is recommended practice to <em>always</em> immediately
|
||||
* follow a call to {@code lock} with a {@code try} block, most
|
||||
* typically in a before/after construction such as:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class X {
|
||||
* private final ReentrantLock lock = new ReentrantLock();
|
||||
* // ...
|
||||
*
|
||||
* public void m() {
|
||||
* lock.lock(); // block until condition holds
|
||||
* try {
|
||||
* // ... method body
|
||||
* } finally {
|
||||
* lock.unlock()
|
||||
* }
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>In addition to implementing the {@link Lock} interface, this
|
||||
* class defines a number of {@code public} and {@code protected}
|
||||
* methods for inspecting the state of the lock. Some of these
|
||||
* methods are only useful for instrumentation and monitoring.
|
||||
*
|
||||
* <p>Serialization of this class behaves in the same way as built-in
|
||||
* locks: a deserialized lock is in the unlocked state, regardless of
|
||||
* its state when serialized.
|
||||
*
|
||||
* <p>This lock supports a maximum of 2147483647 recursive locks by
|
||||
* the same thread. Attempts to exceed this limit result in
|
||||
* {@link Error} throws from locking methods.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class ReentrantLock implements Lock, java.io.Serializable {
|
||||
private static final long serialVersionUID = 7373984872572414699L;
|
||||
/** Synchronizer providing all implementation mechanics */
|
||||
private final Sync sync;
|
||||
|
||||
/**
|
||||
* Base of synchronization control for this lock. Subclassed
|
||||
* into fair and nonfair versions below. Uses AQS state to
|
||||
* represent the number of holds on the lock.
|
||||
*/
|
||||
abstract static class Sync extends AbstractQueuedSynchronizer {
|
||||
private static final long serialVersionUID = -5179523762034025860L;
|
||||
|
||||
/**
|
||||
* Performs non-fair tryLock. tryAcquire is implemented in
|
||||
* subclasses, but both need nonfair try for trylock method.
|
||||
*/
|
||||
@ReservedStackAccess
|
||||
final boolean nonfairTryAcquire(int acquires) {
|
||||
final Thread current = Thread.currentThread();
|
||||
int c = getState();
|
||||
if (c == 0) {
|
||||
if (compareAndSetState(0, acquires)) {
|
||||
setExclusiveOwnerThread(current);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (current == getExclusiveOwnerThread()) {
|
||||
int nextc = c + acquires;
|
||||
if (nextc < 0) // overflow
|
||||
throw new Error("Maximum lock count exceeded");
|
||||
setState(nextc);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ReservedStackAccess
|
||||
protected final boolean tryRelease(int releases) {
|
||||
int c = getState() - releases;
|
||||
if (Thread.currentThread() != getExclusiveOwnerThread())
|
||||
throw new IllegalMonitorStateException();
|
||||
boolean free = false;
|
||||
if (c == 0) {
|
||||
free = true;
|
||||
setExclusiveOwnerThread(null);
|
||||
}
|
||||
setState(c);
|
||||
return free;
|
||||
}
|
||||
|
||||
protected final boolean isHeldExclusively() {
|
||||
// While we must in general read state before owner,
|
||||
// we don't need to do so to check if current thread is owner
|
||||
return getExclusiveOwnerThread() == Thread.currentThread();
|
||||
}
|
||||
|
||||
final ConditionObject newCondition() {
|
||||
return new ConditionObject();
|
||||
}
|
||||
|
||||
// Methods relayed from outer class
|
||||
|
||||
final Thread getOwner() {
|
||||
return getState() == 0 ? null : getExclusiveOwnerThread();
|
||||
}
|
||||
|
||||
final int getHoldCount() {
|
||||
return isHeldExclusively() ? getState() : 0;
|
||||
}
|
||||
|
||||
final boolean isLocked() {
|
||||
return getState() != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstitutes the instance from a stream (that is, deserializes it).
|
||||
*/
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws java.io.IOException, ClassNotFoundException {
|
||||
s.defaultReadObject();
|
||||
setState(0); // reset to unlocked state
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync object for non-fair locks
|
||||
*/
|
||||
static final class NonfairSync extends Sync {
|
||||
private static final long serialVersionUID = 7316153563782823691L;
|
||||
protected final boolean tryAcquire(int acquires) {
|
||||
return nonfairTryAcquire(acquires);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync object for fair locks
|
||||
*/
|
||||
static final class FairSync extends Sync {
|
||||
private static final long serialVersionUID = -3000897897090466540L;
|
||||
/**
|
||||
* Fair version of tryAcquire. Don't grant access unless
|
||||
* recursive call or no waiters or is first.
|
||||
*/
|
||||
@ReservedStackAccess
|
||||
protected final boolean tryAcquire(int acquires) {
|
||||
final Thread current = Thread.currentThread();
|
||||
int c = getState();
|
||||
if (c == 0) {
|
||||
if (!hasQueuedPredecessors() &&
|
||||
compareAndSetState(0, acquires)) {
|
||||
setExclusiveOwnerThread(current);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (current == getExclusiveOwnerThread()) {
|
||||
int nextc = c + acquires;
|
||||
if (nextc < 0)
|
||||
throw new Error("Maximum lock count exceeded");
|
||||
setState(nextc);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of {@code ReentrantLock}.
|
||||
* This is equivalent to using {@code ReentrantLock(false)}.
|
||||
*/
|
||||
public ReentrantLock() {
|
||||
sync = new NonfairSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of {@code ReentrantLock} with the
|
||||
* given fairness policy.
|
||||
*
|
||||
* @param fair {@code true} if this lock should use a fair ordering policy
|
||||
*/
|
||||
public ReentrantLock(boolean fair) {
|
||||
sync = fair ? new FairSync() : new NonfairSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires the lock.
|
||||
*
|
||||
* <p>Acquires the lock if it is not held by another thread and returns
|
||||
* immediately, setting the lock hold count to one.
|
||||
*
|
||||
* <p>If the current thread already holds the 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 lock has been acquired,
|
||||
* at which time the lock hold count is set to one.
|
||||
*/
|
||||
public void lock() {
|
||||
sync.acquire(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires the lock unless the current thread is
|
||||
* {@linkplain Thread#interrupt interrupted}.
|
||||
*
|
||||
* <p>Acquires the lock if it is not held by another thread and returns
|
||||
* immediately, setting the 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 lock is acquired by the current thread; or
|
||||
*
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts} the
|
||||
* current thread.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p>If the 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 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 lock only if it is not held by another thread at the time
|
||||
* of invocation.
|
||||
*
|
||||
* <p>Acquires the lock if it is not held by another thread and
|
||||
* returns immediately with the value {@code true}, setting the
|
||||
* 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 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 lock was already held by the current
|
||||
* thread; and {@code false} otherwise
|
||||
*/
|
||||
public boolean tryLock() {
|
||||
return sync.nonfairTryAcquire(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires the 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 lock if it is not held by another thread and returns
|
||||
* immediately with the value {@code true}, setting the 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 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 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 lock is acquired then the value {@code true} is returned and
|
||||
* 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 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 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 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 unlock() {
|
||||
sync.release(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Condition} instance for use with this
|
||||
* {@link Lock} instance.
|
||||
*
|
||||
* <p>The returned {@link Condition} instance supports the same
|
||||
* usages as do the {@link Object} monitor methods ({@link
|
||||
* Object#wait() wait}, {@link Object#notify notify}, and {@link
|
||||
* Object#notifyAll notifyAll}) when used with the built-in
|
||||
* monitor lock.
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li>If this lock is not held when any of the {@link Condition}
|
||||
* {@linkplain Condition#await() waiting} or {@linkplain
|
||||
* Condition#signal signalling} methods are called, then an {@link
|
||||
* IllegalMonitorStateException} is thrown.
|
||||
*
|
||||
* <li>When the condition {@linkplain Condition#await() waiting}
|
||||
* methods are called the lock is released and, before they
|
||||
* return, the lock is reacquired and the lock hold count restored
|
||||
* to what it was when the method was called.
|
||||
*
|
||||
* <li>If a thread is {@linkplain Thread#interrupt interrupted}
|
||||
* while waiting then the wait will terminate, an {@link
|
||||
* InterruptedException} will be thrown, and the thread's
|
||||
* interrupted status will be cleared.
|
||||
*
|
||||
* <li>Waiting threads are signalled in FIFO order.
|
||||
*
|
||||
* <li>The ordering of lock reacquisition for threads returning
|
||||
* from waiting methods is the same as for threads initially
|
||||
* acquiring the lock, which is in the default case not specified,
|
||||
* but for <em>fair</em> locks favors those threads that have been
|
||||
* waiting the longest.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* @return the Condition object
|
||||
*/
|
||||
public Condition newCondition() {
|
||||
return sync.newCondition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the number of holds on this lock by the current thread.
|
||||
*
|
||||
* <p>A thread has a hold on a lock for each lock action that is not
|
||||
* matched by an unlock action.
|
||||
*
|
||||
* <p>The hold count information is typically only used for testing and
|
||||
* debugging purposes. For example, if a certain section of code should
|
||||
* not be entered with the lock already held then we can assert that
|
||||
* fact:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class X {
|
||||
* ReentrantLock lock = new ReentrantLock();
|
||||
* // ...
|
||||
* public void m() {
|
||||
* assert lock.getHoldCount() == 0;
|
||||
* lock.lock();
|
||||
* try {
|
||||
* // ... method body
|
||||
* } finally {
|
||||
* lock.unlock();
|
||||
* }
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* @return the number of holds on this lock by the current thread,
|
||||
* or zero if this lock is not held by the current thread
|
||||
*/
|
||||
public int getHoldCount() {
|
||||
return sync.getHoldCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries if this lock is held by the current thread.
|
||||
*
|
||||
* <p>Analogous to the {@link Thread#holdsLock(Object)} method for
|
||||
* built-in monitor locks, this method is typically used for
|
||||
* debugging and testing. For example, a method that should only be
|
||||
* called while a lock is held can assert that this is the case:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class X {
|
||||
* ReentrantLock lock = new ReentrantLock();
|
||||
* // ...
|
||||
*
|
||||
* public void m() {
|
||||
* assert lock.isHeldByCurrentThread();
|
||||
* // ... method body
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>It can also be used to ensure that a reentrant lock is used
|
||||
* in a non-reentrant manner, for example:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class X {
|
||||
* ReentrantLock lock = new ReentrantLock();
|
||||
* // ...
|
||||
*
|
||||
* public void m() {
|
||||
* assert !lock.isHeldByCurrentThread();
|
||||
* lock.lock();
|
||||
* try {
|
||||
* // ... method body
|
||||
* } finally {
|
||||
* lock.unlock();
|
||||
* }
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* @return {@code true} if current thread holds this lock and
|
||||
* {@code false} otherwise
|
||||
*/
|
||||
public boolean isHeldByCurrentThread() {
|
||||
return sync.isHeldExclusively();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries if this lock is held by any thread. This method is
|
||||
* designed for use in monitoring of the system state,
|
||||
* not for synchronization control.
|
||||
*
|
||||
* @return {@code true} if any thread holds this lock and
|
||||
* {@code false} otherwise
|
||||
*/
|
||||
public boolean isLocked() {
|
||||
return sync.isLocked();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this lock has fairness set true.
|
||||
*
|
||||
* @return {@code true} if this lock has fairness set true
|
||||
*/
|
||||
public final boolean isFair() {
|
||||
return sync instanceof FairSync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thread that currently owns this lock, or
|
||||
* {@code 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 {@code 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.
|
||||
*
|
||||
* @return the owner, or {@code null} if not owned
|
||||
*/
|
||||
protected Thread getOwner() {
|
||||
return sync.getOwner();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries whether any threads are waiting to acquire this lock. Note that
|
||||
* because cancellations may occur at any time, a {@code 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.
|
||||
*
|
||||
* @return {@code true} if there may be other threads waiting to
|
||||
* acquire the lock
|
||||
*/
|
||||
public final boolean hasQueuedThreads() {
|
||||
return sync.hasQueuedThreads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries whether the given thread is waiting to acquire this
|
||||
* lock. Note that because cancellations may occur at any time, a
|
||||
* {@code 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.
|
||||
*
|
||||
* @param thread the thread
|
||||
* @return {@code true} if the given thread is queued waiting for this lock
|
||||
* @throws NullPointerException if the thread is null
|
||||
*/
|
||||
public final boolean hasQueuedThread(Thread thread) {
|
||||
return sync.isQueued(thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an estimate of the number of threads waiting to acquire
|
||||
* this lock. 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.
|
||||
*
|
||||
* @return the estimated number of threads waiting for this lock
|
||||
*/
|
||||
public final int getQueueLength() {
|
||||
return sync.getQueueLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection containing threads that may be waiting to
|
||||
* acquire this lock. 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.
|
||||
*
|
||||
* @return the collection of threads
|
||||
*/
|
||||
protected Collection<Thread> getQueuedThreads() {
|
||||
return sync.getQueuedThreads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries whether any threads are waiting on the given condition
|
||||
* associated with this lock. Note that because timeouts and
|
||||
* interrupts may occur at any time, a {@code true} return does
|
||||
* not guarantee that a future {@code signal} will awaken any
|
||||
* threads. This method is designed primarily for use in
|
||||
* monitoring of the system state.
|
||||
*
|
||||
* @param condition the condition
|
||||
* @return {@code true} if there are any waiting threads
|
||||
* @throws IllegalMonitorStateException if this lock is not held
|
||||
* @throws IllegalArgumentException if the given condition is
|
||||
* not associated with this lock
|
||||
* @throws NullPointerException if the condition is null
|
||||
*/
|
||||
public boolean hasWaiters(Condition condition) {
|
||||
if (condition == null)
|
||||
throw new NullPointerException();
|
||||
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
|
||||
throw new IllegalArgumentException("not owner");
|
||||
return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an estimate of the number of threads waiting on the
|
||||
* given condition associated with this lock. 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.
|
||||
*
|
||||
* @param condition the condition
|
||||
* @return the estimated number of waiting threads
|
||||
* @throws IllegalMonitorStateException if this lock is not held
|
||||
* @throws IllegalArgumentException if the given condition is
|
||||
* not associated with this lock
|
||||
* @throws NullPointerException if the condition is null
|
||||
*/
|
||||
public int getWaitQueueLength(Condition condition) {
|
||||
if (condition == null)
|
||||
throw new NullPointerException();
|
||||
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
|
||||
throw new IllegalArgumentException("not owner");
|
||||
return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection containing those threads that may be
|
||||
* waiting on the given condition associated with this lock.
|
||||
* 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 condition monitoring facilities.
|
||||
*
|
||||
* @param condition the condition
|
||||
* @return the collection of threads
|
||||
* @throws IllegalMonitorStateException if this lock is not held
|
||||
* @throws IllegalArgumentException if the given condition is
|
||||
* not associated with this lock
|
||||
* @throws NullPointerException if the condition is null
|
||||
*/
|
||||
protected Collection<Thread> getWaitingThreads(Condition condition) {
|
||||
if (condition == null)
|
||||
throw new NullPointerException();
|
||||
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
|
||||
throw new IllegalArgumentException("not owner");
|
||||
return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string identifying this lock, as well as its lock state.
|
||||
* The state, in brackets, includes either the String {@code "Unlocked"}
|
||||
* or the String {@code "Locked by"} followed by the
|
||||
* {@linkplain Thread#getName name} of the owning thread.
|
||||
*
|
||||
* @return a string identifying this lock, as well as its lock state
|
||||
*/
|
||||
public String toString() {
|
||||
Thread o = sync.getOwner();
|
||||
return super.toString() + ((o == null) ?
|
||||
"[Unlocked]" :
|
||||
"[Locked by thread " + o.getName() + "]");
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interfaces and classes providing a framework for locking and waiting
|
||||
* for conditions that is distinct from built-in synchronization and
|
||||
* monitors. The framework permits much greater flexibility in the use of
|
||||
* locks and conditions, at the expense of more awkward syntax.
|
||||
*
|
||||
* <p>The {@link java.util.concurrent.locks.Lock} interface supports
|
||||
* locking disciplines that differ in semantics (reentrant, fair, etc),
|
||||
* and that can be used in non-block-structured contexts including
|
||||
* hand-over-hand and lock reordering algorithms. The main implementation
|
||||
* is {@link java.util.concurrent.locks.ReentrantLock}.
|
||||
*
|
||||
* <p>The {@link java.util.concurrent.locks.ReadWriteLock} interface
|
||||
* similarly defines locks that may be shared among readers but are
|
||||
* exclusive to writers. Only a single implementation, {@link
|
||||
* java.util.concurrent.locks.ReentrantReadWriteLock}, is provided, since
|
||||
* it covers most standard usage contexts. But programmers may create
|
||||
* their own implementations to cover nonstandard requirements.
|
||||
*
|
||||
* <p>The {@link java.util.concurrent.locks.Condition} interface
|
||||
* describes condition variables that may be associated with Locks.
|
||||
* These are similar in usage to the implicit monitors accessed using
|
||||
* {@code Object.wait}, but offer extended capabilities.
|
||||
* In particular, multiple {@code Condition} objects may be associated
|
||||
* with a single {@code Lock}. To avoid compatibility issues, the
|
||||
* names of {@code Condition} methods are different from the
|
||||
* corresponding {@code Object} versions.
|
||||
*
|
||||
* <p>The {@link java.util.concurrent.locks.AbstractQueuedSynchronizer}
|
||||
* class serves as a useful superclass for defining locks and other
|
||||
* synchronizers that rely on queuing blocked threads. The {@link
|
||||
* java.util.concurrent.locks.AbstractQueuedLongSynchronizer} class
|
||||
* provides the same functionality but extends support to 64 bits of
|
||||
* synchronization state. Both extend class {@link
|
||||
* java.util.concurrent.locks.AbstractOwnableSynchronizer}, a simple
|
||||
* class that helps record the thread currently holding exclusive
|
||||
* synchronization. The {@link java.util.concurrent.locks.LockSupport}
|
||||
* class provides lower-level blocking and unblocking support that is
|
||||
* useful for those developers implementing their own customized lock
|
||||
* classes.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
package java.util.concurrent.locks;
|
Loading…
Add table
Add a link
Reference in a new issue