Lock接口
看看Lock接口的结构和lock接口的具体实现类ReentrantLock,通过对它们的揣摩,能多少知道一些“锁”的工作原理。
Lock接口:
package edu.emory.mathcs.backport.java.util.concurrent.locks;
import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
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 <tt>Lock</tt> 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
* <tt>Lock</tt> implementation.
*
**/
void lock();
方法功能:
申请锁
详细描述:
如果当前锁无效(无法获得),则申请该锁的线程将挂起等待直到获得有效的锁。
对实现类的考虑:
具体实现类要能够检测一些使用中的错误(例如死锁)并按照相应情况抛出异常。这些具体的异常情况必须在Lock的实现类中有所体现。
/**
* Acquires the lock unless the current thread is
* {@link 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 {@link 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 {@link 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 <tt>Lock</tt> 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 <tt>Lock</tt> implementation.
*
* @throws InterruptedException if the current thread is interrupted
* while acquiring the lock (and interruption of lock acquisition is
* supported).
*
* @see Thread#interrupt
*
**/
void lockInterruptibly() throws InterruptedException;
方法功能:
申请锁,除非当前申请线程被中断。
详细描述:
申请锁时如果锁是有效的(未被其它线程所占用),则立即返回;如果锁是无效的,则申请该锁的线程(即称为当前线程)将挂起等待直到获得有效的锁,这时会有两种情况发生:
1. 当前线程获得锁。
2. 当前线程被其它线程所中断,而且锁申请的中断被支持。如果当前线程对这个方法来说存在线程被中断的状态的登记;或者锁申请的中断被支持,则一个InterruptedException异常将被抛出,当前线程的中断状态将被清除。
对实现类的考虑:
对于某些实现来说支持锁获取的中断可能是不可能的,如果可能也要花费大量的操作。开发人员要注意到这个事实。写实现类的文档时要对它有所说明。一个实现能支持根据在正常方法上的中断而返回。具体实现类要能够检测一些使用中的错误(例如死锁)并按照相应情况抛出异常。这些具体的异常情况必须在Lock的实现类中有所体现。当正在申请锁时(如果申请锁的中断被支持),当前线程被中断,则一个中断异常将被抛出。
/**
* 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 <tt>true</tt>.
* If the lock is not available then this method will return
* immediately with the value <tt>false</tt>.
* <p>A typical usage idiom for this method would be:
* <pre>
* 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 <tt>true</tt> if the lock was acquired and <tt>false</tt>
* otherwise.
**/
boolean tryLock();
方法功能:
只当锁是有效的(没有线程占用)时,才获取锁。
详细描述:
如果锁是有效的,则获取锁并立即返回true;否则将立即返回false。
该方法的典型用例:
Lock lock = ...;
if (lock.tryLock()) {
try {
// manipulate protected state
} finally {
lock.unlock();
}
} else {
// perform alternative actions
}
这种用法确保如果锁被获得的话,将被解锁,而如果锁没有被获得的话,不用去尝试解锁。
/**
* Acquires the lock if it is free within the given waiting time and the
* current thread has not been {@link Thread#interrupt interrupted}.
*
* <p>If the lock is available this method returns immediately
* with the value <tt>true</tt>.
* 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 {@link 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 <tt>true</tt> is returned.
* <p>If the current thread:
* <ul>
* <li>has its interrupted status set on entry to this method; or
* <li>is {@link 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 <tt>false</tt>
* 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 <tt>Lock</tt> 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
* <tt>Lock</tt> implementation.
*
* @param time the maximum time to wait for the lock
* @param unit the time unit of the <tt>time</tt> argument.
* @return <tt>true</tt> if the lock was acquired and <tt>false</tt>
* 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).
*
* @see Thread#interrupt
*
**/
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
方法功能:
在给定时间内获取锁
详细描述:
如果在一定的等待时间内锁是有效的,并且当前线程没有被中断的话,当前线程将获得该锁;如果锁是无效的,则当前线程将挂起直到以下的三种情况之一发生:
1.在一定的时间内锁被当前线程获得;
2.其它线程中断了当前线程,并且锁申请的中断被支持;
3.在一定时间内当前线程没有获得锁,即等待时间超出了给定值。
情况1发生时,锁被当前线程获取,并返回true;
情况2发生时,如果对本方法来讲,当前线程的中断状态被登记或者申请锁时,锁申请的中断被支持,则InterruptedException将被抛出,当前线程的中断状态被清除。
情况3发生时,返回false。如果给定的时间期限<=0,则本方法将不作等待。
对实现类的考虑:
一些实现支持锁获取的中断不大可能,而且如果支持的话将付出大量的操作。开发人员应该注意这种情况。并且实现类必须将此情况写入文档。一个实现类能够在执行方法时被中断并返回,或者报告超时。具体实现类要能够检测一些使用中的错误(例如死锁)并按照相应情况抛出异常。这些具体的异常情况必须在Lock的实现类中有所体现。当正在申请锁时(如果申请锁的中断被支持),当前线程被中断,则一个中断异常将被抛出。
方法说明:
参数1:等待时间(超时时间)
参数2:TimeUnit类对象
返回值:当获得锁时返回true,当等待超时时返回false。
异常情况:如果当前线程在获取锁时被中断(锁申请的中断被支持),则InterruptedException被抛出
/**
* Releases the lock.
* <p><b>Implementation Considerations</b>
* <p>A <tt>Lock</tt> 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 <tt>Lock</tt> implementation.
**/
void unlock();
方法功能:
释放锁。
对实现类的建议:
锁实现类可以对能够释放锁的线程附加限制,典型的是锁的持有者能够释放锁,当限制被违背时,一个异常将被抛出。任何限制和异常都必须被写入到实现类的文档中。
/**
* Returns a new {@link Condition} instance that is bound to this
* <tt>Lock</tt> 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
* <tt>Lock</tt> implementation and must be documented by that
* implementation.
*
* @return A new {@link Condition} instance for this <tt>Lock</tt>
* instance.
* @throws UnsupportedOperationException if this <tt>Lock</tt>
* implementation does not support conditions.
**/
Condition newCondition();
方法功能:
返回一个新的被绑定到锁上的条件实例。
详细描述:
在调用本方法等待条件实例返回前,当前线程必须首先获得锁。在等待前要调用Condition.await方法自动释放锁和并且在等待返回前重新申请锁。
对实例类的建议:
条件实例操作依靠于锁实现,并且必须写入实例类的文档中。
方法说明:
返回值:返回一个新的被绑定到锁上的条件实例。
异常情况:如果锁不支持条件,则抛出UnsupportedOperationException异常。
}
总结一下,lock接口的方法列表
方法名 | 功能 | 备注 |
lock | 获取锁 | 如果获取不到锁的话,当前线程将挂起直到获得锁。我把它称作“死等”式获取。 |
lockInterruptibly | 以可被中断的方式获取锁 | 如果获取不到锁的话,当前线程将挂起直到获得锁或者当前线程被其他线程中断。我把它称作“悲观死等”式获取。 |
tryLock | 尝试获取锁 | 如果锁有效的话,当前线程立即获取锁并返回true,否则返回false。我称之为“试探”式获取 |
tryLock(long time, TimeUnit unit) | 具有超时机制的尝试获取锁 | 如果锁有效的话,当前线程立即获取锁并返回true;否则等待一个给定的时间,如果在这时间内获得锁,则返回true,否则返回false;另外像lockInterruptibly一样线程有可能在获取的过程中被中断。我称之为“试探超时”式获取 |
releaseLock | 释放锁 |
|
newCondition | 返回当前锁的条件 |
|
比较四种lock方法来讲,“试探”式和“试探超时”式获取锁的方式效率较高。而“死等”和“悲观死等”式效率低,而且在并发线程较多时增加了系统的资源开销,并且当持有锁的线程没有释放锁便被kill掉时,那些等待锁的线程将被永远的挂起。