Javaマルチスレッドロックソースコード分析

package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;

/**
 * 与使用同步方法和语句相比,锁实现提供了更广泛的锁定操作。
 * 它们允许更灵活的结构,可能有相当不同的属性,并可能支持多个关联的Condition对象。
 *
 * <p>锁是一种用来控制多线程对共享资源的访问的工具。
 * 通常,锁提供了对共享资源的排他访问:一次只有一个线程可以获得锁,并且所有对共享资源的访问都需要先获得锁。
 * 然而,有些锁可以允许并发访问共享资源,例如ReadWriteLock的读锁。
 *
 * <p>使用synchronized方法或语句给每个对象关联的隐式监视锁提供访问,但是强制所有锁获取和释放发生固定的方式:
 * 当多个锁被获取,他们必须以相反的顺序释放,和所有的锁都必须在同样的作用域释放它们。
 *
 * <p>虽然同步方法和语句的作用域机制使使用监视锁编程变得更容易,并有助于避免许多涉及锁的常见编程错误,
 * 但在某些情况下,您需要以更灵活的方式使用锁。
 * 例如,一些遍历并发访问数据结构的算法需要使用“hand-over-hand”或“chain locking”:
 * 先获取节点A的锁,然后是节点B,然后释放节点A并获取c,然后释放节点B并获取D,等等。
 * Lock接口的实现允许在不同的范围内获取和释放锁,
 * 并允许以任何顺序获取和释放多个锁,从而支持使用这些技术。
 *
 * <p>随着灵活性的增加,更多的责任也随之而来。
 * 没有了块结构的锁,同步方法和语句就不会自动释放锁。
 * 在大多数情况下,应该使用以下习语:
 *
 *  <pre> {@code
 * Lock l = ...;
 * l.lock();
 * try {
 *   // access the resource protected by this lock
 * } finally {
 *   l.unlock();
 * }}</pre>
 *
 * 当锁定和解锁发生在不同的作用域时,必须小心确保所有在持有锁时执行的代码都受到try-finally或try-catch的保护,以确保在必要时释放锁。
 * 
 *
 * <p>在使用同步方法和语句的基础上,锁实现提供了额外的功能,
 * 提供了获取锁的非阻塞尝试(tryLock())、获取可以中断的锁的尝试(lockInterruptibly,
 * 以及获取可以超时的锁的尝试(tryLock(long, TimeUnit))。
 *
 * <p>锁类还可以提供与隐式监控锁截然不同的行为和语义,
 * 比如保证排序、不可重入使用或死锁检测。
 * 如果实现提供了这样专门化的语义,那么实现必须记录这些语义。
 *
 * <p>请注意,锁实例只是普通对象,它们本身可以作为同步语句中的目标。
 * 获取锁实例的monitor锁与调用该实例的任何锁方法没有指定的关系。
 * 建议您永远不要以这种方式使用Lock实例,除非是在它们自己的实现中。
 *
 * <p>除非有特别说明,传递任何参数的空值都会导致抛出NullPointerException。
 *
 * <h3>内存同步</h3>
 *
 * <p>所有的锁实现都必须执行内置的monitor锁提供的相同的内存同步语义,正如Java语言规范(17.4内存模型)中描述的那样:
 * <ul>
 * <li>一个成功的锁操作和一个成功的锁操作具有相同的内存同步效果。
 * <li>一个成功的解锁操作与一个成功的解锁操作具有相同的内存同步效果。
 * </ul>
 *
 * 不成功的锁定和解锁操作,以及重入锁定/解锁操作,不需要任何内存同步效果。
 *
 * <h3>实现注意事项</h3>
 *
 * <p>三种形式的锁获取(可中断、不可中断和定时)可能在它们的性能特征、顺序保证或其他实现质量上有所不同。
 * 此外,中断正在获取的锁的能力在给定的锁类中可能是不可用的。
 * 因此,实现不需要为所有三种形式的锁获取定义完全相同的保证或语义,也不需要支持中断正在进行的锁获取。
 * 需要一个实现来清楚地记录每个锁定方法提供的语义和保证。
 * 它还必须遵守在这个接口中定义的中断语义,
 * 在某种程度上,锁获取的中断是支持的:
 * 要么完全支持,要么只支持方法层面。
 *
 * <p>由于中断通常意味着取消,并且对中断的检查经常是不频繁的,一个实现可以更倾向于响应中断而不是从正常的方法返回。
 * 这是正确的,即使它可以证明中断发生在另一个操作可能已经解除线程阻塞之后。实现应该记录这种行为。
 *
 * @see ReentrantLock
 * @see Condition
 * @see ReadWriteLock
 *
 * @since 1.5
 * @author Doug Lea
 */
public interface Lock {

    /**
     * 获得锁。
     *
     * <p>如果锁不可用,那么当前线程就会因为线程调度的目的而被禁用,并处于休眠状态,直到获得锁为止。
     *
     * <p><b>实现注意事项</b>
     *
     * <p>锁的实现可能能够检测到锁的错误使用,比如可能导致死锁的调用,
     * 并可能在这种情况下抛出(未检查的)异常。环境和异常类型必须由该锁实现记录。
     */
    void lock();

    /**
     * 除非当前线程被中断,否则将获得锁。
     *
     * <p>如果锁可用,则获取锁并立即返回。
     *
     * <p>如果锁不可用,那么当前线程就会因为线程调度的目的而被禁用,并且处于休眠状态,直到以下两种情况发生:
     *
     * <ul>
     * <li>锁是由当前线程获取的;或
     * <li>其他一些线程会中断当前线程,并且支持中断获取锁。
     * </ul>
     *
     * <p>如果当前线程:
     * <ul>
     * <li>在进入该方法时设置中断状态;或
     * <li>获取锁时被中断,并且支持锁获取的中断,
     * </ul>
     * 然后抛出InterruptedException,并清除当前线程的中断状态。
     *
     * <p><b>实现注意事项</b>
     *
     * <p>在某些实现中,中断锁获取的能力可能是不可能的,如果可能的话,这可能是一个昂贵的操作。
     * 程序员应该意识到可能是这种情况。在这种情况下,实现应该记录在案。
     *
     * <p>实现可以支持响应中断超常方法的返回。
     *
     * <p>锁的实现也能检测锁的异常使用,如引起死锁的调用,并在这种情况下抛出(未检查的)异常。环境和异常类型必须由该锁实现记录。
     *
     * @throws InterruptedException if the current thread is
     *         interrupted while acquiring the lock (and interruption
     *         of lock acquisition is supported)
     */
    void lockInterruptibly() throws InterruptedException;

    /**
     * 只有在调用时锁是空闲的时,才获取锁。
     *
     * <p>如果锁可用,则获取锁,并立即返回值为true。如果锁不可用,这个方法将立即返回false。
     *
     * <p>这种方法的典型用法是:
     *  <pre> {@code
     * Lock lock = ...;
     * if (lock.tryLock()) {
     *   try {
     *     // manipulate protected state
     *   } finally {
     *     lock.unlock();
     *   }
     * } else {
     *   // perform alternative actions
     * }}</pre>
     *
     *这种用法确保了如果该锁被获取,它将被解锁,并且如果该锁没有被获取,它将不会尝试解锁。
     *
     * @return {@code true} if the lock was acquired and
     *         {@code false} otherwise
     */
    boolean tryLock();

    /**
     * 如果锁在给定的等待时间内是空闲的,并且当前线程没有被中断,则获取锁。
     *
     * <p>如果锁可用,这个方法立即返回值true。
     * 如果锁不可用,那么当前线程在线程调度中会被禁用,并处于休眠状态,直到以下三种情况之一发生:
     * <ul>
     * <li>锁是由当前线程获取的;或
     * <li>其他线程中断当前线程,并且支持中断获取锁;或
     * <li>经过指定的等待时间
     * </ul>
     *
     * <p>如果获得了锁,则返回值true。
     *
     * <p>如果当前线程:
     * <ul>
     * <li>在进入该方法时设置中断状态;或
     * <li>在获取锁时被中断,并且支持锁获取的中断,
     * </ul>
     * 然后抛出InterruptedException,并清除当前线程的中断状态。
     *
     * <p>如果指定的等待时间过去了,则返回值false。
     * 如果时间小于或等于零,该方法将根本不等待。
     *
     * <p><b>实现注意事项</b>
     *
     * <p>在某些实现中,中断锁获取的能力可能是不可能的,如果可能的话,可能是一个昂贵的操作。
     * 程序员应该意识到可能是这种情况。在这种情况下,实现应该记录在案。
     *
     * <p>实现可以支持响应中断而不是正常的方法返回,或者报告超时。
     *
     * <p>锁的实现也能探测锁的错误使用,如引起死锁的调用,并在这种情况下抛出(未检查的)异常。环境和异常类型必须由该锁实现记录。
     *
     * @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;

    /**
     * 释放锁。
     *
     * <p><b>实现注意事项</b>
     *
     * <p>锁的实现通常会对线程释放锁施加限制(通常只有锁的持有者才能释放锁),
     * 并且如果违反了限制,可能会抛出(未检查的)异常。
     * 任何限制和异常类型都必须由该锁实现记录。
     */
    void unlock();

    /**
     * 返回绑定到此锁实例的新条件实例。
     *
     * <p>在等待条件之前,锁必须由当前线程持有。
     * 调用Condition.await()会在等待之前自动释放锁,并在等待返回之前重新获取锁。
     *
     * <p><b>实现注意事项</b>
     *
     * <p>条件实例的确切操作取决于锁的实现,必须由实现记录。
     *
     * @return A new {@link Condition} instance for this {@code Lock} instance
     * @throws UnsupportedOperationException if this {@code Lock}
     *         implementation does not support conditions
     */
    Condition newCondition();
}

 

おすすめ

転載: blog.csdn.net/xushiyu1996818/article/details/112631462
おすすめ