模块  java.base

Interface Lock

  • 所有已知实现类:
    ReentrantLockReentrantReadWriteLock.ReadLockReentrantReadWriteLock.WriteLock

    public interface Lock
    Lock实现提供了比使用synchronized方法和语句可以获得的更广泛的锁定操作。 它们允许更灵活的结构,可能具有完全不同的属性,并且可能支持多个关联的Condition对象。

    锁是用于控制多个线程对共享资源的访问的工具。 通常,锁提供对共享资源的独占访问:一次只有一个线程可以获取锁,并且对共享资源的所有访问都需要首先获取锁。 但是,某些锁可能允许并发访问共享资源,例如ReadWriteLock的读锁定。

    使用synchronized方法或语句可以访问与每个对象关联的隐式监视器锁,但强制所有锁获取和释放以块结构方式发生:当获取多个锁时,它们必须以相反的顺序释放,并且所有锁必须在获取它们的相同词法范围内释放。

    虽然synchronized方法和语句的作用域机制使得使用监视器锁更容易编程,并且有助于避免许多涉及锁的常见编程错误,但有时您需要以更灵活的方式使用锁。 例如,一些用于遍历并发访问的数据结构的算法需要使用“hand-hand-hand”或“chain locking”:获取节点A的锁,然后获取节点B,然后释放A并获取C,然后释放B并获得D等。 Lock接口的实现允许通过允许在不同范围内获取和释放锁来允许使用这种技术,并允许以任何顺序获取和释放多个锁。

    随着这种增加的灵活性带来额外的责 缺少块结构锁定会删除synchronized方法和语句发生的锁定的自动释放。 在大多数情况下,应使用以下习语:

       Lock l = ...; l.lock(); try { // access the resource protected by this lock } finally { l.unlock(); } 
    当锁定和解锁发生在不同的范围内时,必须注意确保在保持锁定时执行的所有代码都受try-finally或try-catch保护,以确保在必要时释放锁定。

    Lock实现通过提供非阻塞尝试获取锁( tryLock() ),尝试获取可以被中断的锁( lockInterruptibly() ,以及尝试获取可以锁定的锁)来提供使用synchronized方法和语句的附加功能超时( tryLock(long, TimeUnit) )。

    Lock类还可以提供与隐式监视器锁完全不同的行为和语义,例如保证排序,非重入使用或死锁检测。 如果实现提供了这样的专用语义,那么实现必须记录那些语义。

    请注意, Lock实例只是普通对象,它们本身可以用作synchronized语句中的目标。 获取Lock实例的监视器锁定与调用该实例的任何lock()方法没有指定的关系。 为避免混淆,建议您不要以这种方式使用Lock实例,除非在他们自己的实现中。

    除非另有说明, null为任何参数传递null值将导致抛出NullPointerException

    内存同步

    所有Lock实现必须强制执行内置监视器锁提供的相同内存同步语义,如Chapter 17 of The Java™ Language Specification中所述

    • 成功的lock操作具有与成功锁定操作相同的内存同步效果。
    • 成功的unlock操作具有与成功解锁操作相同的内存同步效果。
    不成功的锁定和解锁操作以及重入锁定/解锁操作不需要任何内存同步效果。

    实施注意事项

    锁定获取的三种形式(可中断,不可中断和定时)可能在性能特征,排序保证或其他实现质量方面有所不同。 此外,在给定的Lock类中可能无法中断正在进行的锁定获取的能力。 因此,不需要实现为所有三种形式的锁获取定义完全相同的保证或语义,也不需要支持正在进行的锁获取的中断。 需要一种实现来清楚地记录每种锁定方法提供的语义和保证。 它还必须遵守此接口中定义的中断语义,以支持锁获取的中断:完全或仅在方法入口上。

    由于中断通常意味着取消,并且中断检查通常不常见,因此实现可以有利于响应正常方法返回的中断。 即使可以显示在另一个操作可能已取消阻塞线程之后发生中断,也是如此。 实现应记录此行为。

    从以下版本开始:
    1.5
    另请参见:
    ReentrantLockConditionReadWriteLock
    • 方法详细信息

      • lock

        void lock()
        获得锁。

        如果锁定不可用,则当前线程将被禁用以进行线程调度,并且在获取锁定之前处于休眠状态。

        实施注意事项

        Lock实现可能能够检测到锁的错误使用,例如可能导致死锁的调用,并且可能在这种情况下抛出(未经检查的)异常。 环境和异常类型必须由Lock实现记录。

      • lockInterruptibly

        void lockInterruptibly()                throws InterruptedException
        除非当前线程是interrupted,否则获取锁定。

        如果锁定可用则获取锁定并立即返回。

        如果锁不可用,则当前线程将被禁用以进行线程调度,并且在发生以下两种情况之一之前处于休眠状态:

        • 锁定由当前线程获取; 要么
        • 一些其他线程interrupts当前线程,并且支持锁定获取的中断。

        如果当前线程:

        • 在进入此方法时设置其中断状态; 要么
        • 获取锁定时为interrupted ,支持锁定获取中断,
        然后抛出InterruptedException并清除当前线程的中断状态。

        实施注意事项

        在一些实现中中断锁获取的能力可能是不可能的,并且如果可能的话可能是昂贵的操作。 程序员应该知道可能是这种情况。 在这种情况下,实现应该记录。

        实现可以有利于响应正常方法返回的中断。

        Lock实现可能能够检测到锁的错误使用,例如可能导致死锁的调用,并且可能在这种情况下抛出(未经检查的)异常。 环境和异常类型必须由Lock实现记录。

        异常
        InterruptedException - 如果当前线程在获取锁定时被中断(并且支持锁定获取中断)
      • tryLock

        boolean tryLock()
        只有在调用时它是空闲的才能获取锁。

        获取锁定(如果可用)并立即返回值true 如果锁定不可用,则此方法将立即返回值false

        此方法的典型用法习惯是:

           Lock lock = ...; if (lock.tryLock()) { try { // manipulate protected state } finally { lock.unlock(); } } else { // perform alternative actions } 
        此用法可确保锁定在获取时解锁,并且如果未获取锁定则不会尝试解锁。
        结果
        true如果获得锁定, false
      • tryLock

        boolean tryLock​(long time,                TimeUnit unit)         throws InterruptedException
        如果锁在给定的等待时间内是空闲的并且当前线程不是interrupted ,则获取锁。

        如果锁定可用,则此方法立即返回值true 如果锁不可用,那么当前线程将被禁用以进行线程调度,并且在发生以下三种情况之一之前处于休眠状态:

        • 锁定由当前线程获取; 要么
        • 一些其他线程interrupts当前线程,并支持锁获取中断; 要么
        • 指定的等待时间过去了

        如果获取锁定,则返回值true

        如果当前线程:

        • 在进入此方法时设置其中断状态; 要么
        • 获取锁定时为interrupted ,支持锁定获取中断,
        然后抛出InterruptedException并清除当前线程的中断状态。

        如果指定的等待时间过去,则返回值false 如果时间小于或等于零,则该方法将不会等待。

        实施注意事项

        在一些实现中中断锁获取的能力可能是不可能的,并且如果可能的话可能是昂贵的操作。 程序员应该知道可能是这种情况。 在这种情况下,实现应该记录。

        实现可以有利于响应正常方法返回的中断或报告超时。

        Lock实现可能能够检测到锁的错误使用,例如可能导致死锁的调用,并且可能在这种情况下抛出(未经检查的)异常。 环境和异常类型必须由Lock实现记录。

        参数
        time - 等待锁定的最长时间
        unit - time参数的时间单位
        结果
        true如果已获取锁定)和 false如果在获取锁定之前等待时间已过去)
        异常
        InterruptedException - 如果当前线程在获取锁定时被中断(并且支持锁定获取中断)
      • unlock

        void unlock()
        释放锁定。

        实施注意事项

        Lock实现通常会对哪个线程可以释放锁定(通常只有锁的持有者可以释放它)施加限制,并且如果违反了限制,则可能抛出(未经检查的)异常。 任何限制和异常类型必须由Lock实现记录。

      • newCondition

        Condition newCondition()
        返回一个新Condition绑定到该实例Lock实例。

        在等待条件之前,当前线程必须保持锁定。 调用Condition.await()将在等待之前以原子方式释放锁,并在等待返回之前重新获取锁。

        实施注意事项

        Condition实例的确切操作取决于Lock实现,并且必须由该实现记录。

        结果
        Condition实例,该Lock实例
        异常
        UnsupportedOperationException - 如果此 Lock实施不支持条件