Lock接口源代码分析


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

    /**
     * 请求锁
     *
     * 如果锁不可用,那么出于线程调度的目的,当前线程将被禁用,并处于休眠状态,直到获得锁为止。
     *
     * <p><b>实现考虑</b>
     *
     * {@code Lock}实现可能能够检测到锁的错误使用,例如调用会导致死锁,并可能在这种情况下抛出
     * (unchecked)异常。环境和异常类型必须由{@code Lock}实现记录。
     */
    void lock();

    /**
     * 获取锁,除非当前线程是{@linkplain Thread#interrupt interrupted}。
     *
     * <p>如果锁可用获取锁并立即返回。
     *
     * <p>如果锁不可用,那么当前线程将出于线程调度的目的被禁用,并处于休眠状态,直到发生以下两种情况之一:
     *
     * <ul>
     * <li>锁被当前线程获取;或者
     * <li>其他线程{@linkplain Thread#interrupt interrupts}当前线程,支持中断锁获取。
     * </ul>
     *
     * <p>如果当前线程:
     *
     * <ul>
     * <li>在进入此方法时已设置其中断状态;或者
     * <li>是{@linkplain Thread#interrupt interrupted},当获取锁时,支持中断锁获取,
     * </ul>
     * 则抛出{@link InterruptedException},清除当前线程的中断状态。
     * <p><b>实现考虑</b>
     *
     * <p>在某些实现中中断锁获取的能力可能是不可能的,如果可能的话,这可能是一个昂贵的操作。程序员应该意识到情况
     * 可能就是这样。当出现这种情况时,实现应该记录下来。
     *
     * <p>实现更倾向于响应中断而不是正常的方法返回。
     *
     * <p>{@code Lock}实现可能能够检测到锁的错误使用,例如调用会导致死锁,并可能在这种情况下抛出(unchecked)异常。
     * 环境和异常类型必须由{@code Lock}实现记录。
     *
     * @throw InterruptedException 如果当前线程在获取锁时被中断(并且支持中断锁获取)。
     */
    void lockInterruptibly() throws InterruptedException;

    /**
     * 仅当锁在调用时处于空闲状态时才获取锁。
     *
     * <p>如果锁可用,获取锁,并立即返回值{@code true}。如果锁不可用,那么这个方法将立即返回值{@code false}。
     *
     * <p>这个方法的一个典型用法是:
     *
     * <pre>
     *      Lock lock = ...;
     *      if (lock.tryLock()) {
     *          try {
     *              // 操作保护状态
     *          } finally {
     *              lock.unlock();
     *          }
     *      } else {
     *          // 执行选择操作
     *      }
     * </pre>
     * 这种用法确保锁在被获取时是解锁的,如果没有获取锁,则不会尝试解锁。
     *
     * @return 如果获取到锁,返回{@code true},其他情况返回{@code false}
     */
    boolean tryLock();

    /**
     * 如果锁在给定的等待时间内是空闲的,并且当前线程不是{@linkplain Thread#interrupt interrupted},则获取该锁。
     *
     * <p>如果锁可用,该方法立即返回值{@code true}。如果锁不可用,那么出于线程调度的目的,当前线程将被禁用,
     * 并处于休眠状态,直到发生以下三种情况之一:
     *
     * <ul>
     * <li>锁被当前线程获取;或者
     * <li>其他线程{@linkplain Thread#interrupt interrupts}当前线程,支持中断锁获取;或者
     * <li>指定的等待时间已经过了
     * </ul>
     *
     * <p>如果获得锁,则返回值{@code true}。
     *
     * <p>如果当前线程:
     *
     * <ul>
     * <li>在进入此方法时已设置其中断状态;或者
     * <li>是{@linkplain Thread#interrupt interrupted},当获取锁时,支持中断锁获取,
     * </ul>
     * 否则抛出{@link InterruptedException},清除当前线程的中断状态。
     *
     * <p>如果指定的等待时间过去,则返回值{@code false}。如果时间小于或等于零,则该方法根本不会等待。
     *
     * <p><b>实现考虑</b>
     *
     * <p>在某些实现中中断锁获取的能力可能是不可能的,如果可能的话,这可能是一个昂贵的操作。程序员应该意识到情况可能就是这样。
     * 当出现这种情况时,实现应该记录下来。
     *
     * <p>实现更倾向于响应中断而不是正常的方法返回,或者报告超时。
     *
     * <p>{@code Lock}实现可能能够检测到锁的错误使用,例如调用会导致死锁,并可能在这种情况下抛出(unchecked)异常。
     * 环境和异常类型必须由{@code Lock}实现记录。
     *
     * @param time 等待锁的最大时间
     * @param unit {@code time}参数的时间单位
     * @return 如果获得锁,返回{@code true},如果在获得锁之前等待时间超时,则返回{@code false}
     *
     * @throws InterruptedException 如果请求锁的时候,当前线程被中断(并且锁支持捕获中断)
     */
    boolean tryLock(long time, java.util.concurrent.TimeUnit unit) throws InterruptedException;

    /**
     * 释放锁
     *
     * <p><b>实现考虑</b>
     *
     * <p>{@code Lock}实现通常会对哪个线程可以释放锁施加限制(通常只有锁的持有者才能释放锁),如果违反了这个限制,
     * 可能会抛出(unchecked)异常。任何限制和异常类型都必须由{@code Lock}实现记录。
     */
    void unlock();

    /**
     * 返回绑定到这个{@code Lock}实例的一个新的{@link Condition}实例。
     *
     * <p>在等待条件之前,锁必须由当前线程持有。调用{@link Condition#await()}将在等待之前自动释放锁,
     * 并在等待返回之前重新获取锁。
     *
     * <p><b>实现考虑</b>
     *
     * <p>{@link Condition}实例的确切操作依赖于{@code Lock}实现,必须由该实现记录。
     *
     * @return 这个{@code Lock}实例的一个新的{@link Condition}实例
     * @throws UnsupportedOperationException 如果这个{@code Lock}实现不支持条件
     */
    Condition newCondition();
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容