Copyright (c) 2003, 2012 IBM Corporation and others.
This program and the accompanying materials
are made available under the terms of the Eclipse Public License 2.0
which accompanies this distribution, and is available at
https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
Contributors:
IBM - Initial API and implementation
/*******************************************************************************
* Copyright (c) 2003, 2012 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM - Initial API and implementation
*******************************************************************************/
package org.eclipse.core.runtime.jobs;
A lock is used to control access to an exclusive resource.
Locks are reentrant. That is, they can be acquired multiple times by the same thread
without releasing. Locks are only released when the number of successful acquires
equals the number of successful releases.
Locks are capable of detecting and recovering from programming errors that cause
circular waiting deadlocks. When a deadlock between two or more ILock
instances is detected, detailed debugging information is printed to the log file. The
locks will then automatically recover from the deadlock by employing a release
and wait strategy. One thread will lose control of the locks it owns, thus breaking
the deadlock and allowing other threads to proceed. Once that thread's locks are
all available, it will be given exclusive access to all its locks and allowed to proceed.
A thread can only lose locks while it is waiting on an acquire()
call.
Successive acquire attempts by different threads are queued and serviced on
a first come, first served basis.
It is very important that acquired locks eventually get released. Calls to release
should be done in a finally block to ensure they execute. For example:
try {
lock.acquire();
// ... do work here ...
} finally {
lock.release();
}
Note: although lock.acquire
should never fail, it is good practice to place
it inside the try block anyway. Releasing without acquiring is far less catastrophic
than acquiring without releasing.
See Also: - newLock.newLock()
Since: 3.0 @noimplement This interface is not intended to be implemented by clients. @noextend This interface is not intended to be extended by clients.
/**
* A lock is used to control access to an exclusive resource.
* <p>
* Locks are reentrant. That is, they can be acquired multiple times by the same thread
* without releasing. Locks are only released when the number of successful acquires
* equals the number of successful releases.
* </p><p>
* Locks are capable of detecting and recovering from programming errors that cause
* circular waiting deadlocks. When a deadlock between two or more <code>ILock</code>
* instances is detected, detailed debugging information is printed to the log file. The
* locks will then automatically recover from the deadlock by employing a release
* and wait strategy. One thread will lose control of the locks it owns, thus breaking
* the deadlock and allowing other threads to proceed. Once that thread's locks are
* all available, it will be given exclusive access to all its locks and allowed to proceed.
* A thread can only lose locks while it is waiting on an <code>acquire()</code> call.
*
* </p><p>
* Successive acquire attempts by different threads are queued and serviced on
* a first come, first served basis.
* </p><p>
* It is very important that acquired locks eventually get released. Calls to release
* should be done in a finally block to ensure they execute. For example:
* </p>
* <pre>
* try {
* lock.acquire();
* // ... do work here ...
* } finally {
* lock.release();
* }
* </pre>
* <p>
* Note: although <code>lock.acquire</code> should never fail, it is good practice to place
* it inside the try block anyway. Releasing without acquiring is far less catastrophic
* than acquiring without releasing.
* </p>
*
* @see IJobManager#newLock()
* @since 3.0
* @noimplement This interface is not intended to be implemented by clients.
* @noextend This interface is not intended to be extended by clients.
*/
public interface ILock {
Attempts to acquire this lock. If the lock is in use and the specified delay is
greater than zero, the calling thread will block until one of the following happens:
- This lock is available
- The thread is interrupted
- The specified delay has elapsed
While a thread is waiting, locks it already owns may be granted to other threads
if necessary to break a deadlock. In this situation, the calling thread may be blocked
for longer than the specified delay. On returning from this call, the calling thread
will once again have exclusive access to any other locks it owned upon entering
the acquire method.
Params: - delay – the number of milliseconds to delay
Throws: - InterruptedException – if the thread was interrupted
Returns: true
if the lock was successfully acquired, and
false
otherwise.
/**
* Attempts to acquire this lock. If the lock is in use and the specified delay is
* greater than zero, the calling thread will block until one of the following happens:
* <ul>
* <li>This lock is available</li>
* <li>The thread is interrupted</li>
* <li>The specified delay has elapsed</li>
* </ul>
* <p>
* While a thread is waiting, locks it already owns may be granted to other threads
* if necessary to break a deadlock. In this situation, the calling thread may be blocked
* for longer than the specified delay. On returning from this call, the calling thread
* will once again have exclusive access to any other locks it owned upon entering
* the acquire method.
*
* @param delay the number of milliseconds to delay
* @return <code>true</code> if the lock was successfully acquired, and
* <code>false</code> otherwise.
* @exception InterruptedException if the thread was interrupted
*/
boolean acquire(long delay) throws InterruptedException;
Acquires this lock. If the lock is in use, the calling thread will block until the lock
becomes available. If the calling thread owns several locks, it will be blocked
until all threads it requires become available, or until the thread is interrupted.
While a thread is waiting, its locks may be granted to other threads if necessary
to break a deadlock. On returning from this call, the calling thread will
have exclusive access to this lock, and any other locks it owned upon
entering the acquire method.
This implementation ignores attempts to interrupt the thread. If response to
interruption is needed, use the method acquire(long)
/**
* Acquires this lock. If the lock is in use, the calling thread will block until the lock
* becomes available. If the calling thread owns several locks, it will be blocked
* until all threads it requires become available, or until the thread is interrupted.
* While a thread is waiting, its locks may be granted to other threads if necessary
* to break a deadlock. On returning from this call, the calling thread will
* have exclusive access to this lock, and any other locks it owned upon
* entering the acquire method.
* <p>
* This implementation ignores attempts to interrupt the thread. If response to
* interruption is needed, use the method <code>acquire(long)</code>
*/
void acquire();
Returns the number of nested acquires on this lock that have not been released.
This is the number of times that release() must be called before the lock is
freed.
Returns: the number of nested acquires that have not been released
/**
* Returns the number of nested acquires on this lock that have not been released.
* This is the number of times that release() must be called before the lock is
* freed.
*
* @return the number of nested acquires that have not been released
*/
int getDepth();
Releases this lock. Locks must only be released by the thread that currently
owns the lock.
/**
* Releases this lock. Locks must only be released by the thread that currently
* owns the lock.
*/
void release();
}