jdk-Lock类的翻译

1. Lock类的说明

  1. Lock 的实现类提供了比synchronized方法和语句的更多的扩展的锁操作
    他们允许更加灵活多变的结构,可能有相当不同的属性,可能支持多种的关联Condition对象
  2. 锁是一种工具,用于控制多个线程对共享资源的访问。通常,锁提供对共享资源的独占访问(exclusive access):一次只有一个线程可以获取锁,并且所有对共享资源的访问都要求首先获取锁。然而,某些锁可能允许对共享资源的并发访问,例如ReadWriteLock中的读锁。
  3. 使用synchronized方法或语句提供了对每个对象关联的隐式监视器锁(implicit monitor )的访问,但强制所有的锁获取和释放都必须以块结构的方式进行:当获取多个锁时,它们必须按相反的顺序释放,并且所有锁都必须在获取它们的同一词法范围内释放。
  4. 虽然对于synchronized方法和语句的范围机制使得使用监视器锁编程变得更加容易,并且有助于避免许多涉及锁的常见编程错误,但在某些情况下,你需要以更加灵活的方式来处理锁。例如,有些算法用于遍历并发访问的数据结构时,需要使用“hand-over-hand”或“chain locking”的方式:你先获取节点A的锁,然后是节点B的锁,接着释放A并获取C的锁,再释放B并获取D的锁,依此类推。实现Lock接口的类通过允许在不同的范围内获取和释放锁,以及允许多个锁以任意顺序获取和释放,从而支持使用这样的技术。
  5. 随着灵活性的增加,也带来了额外的责任。块结构锁定的缺失意味着不会像synchronized方法和语句那样自动释放锁。在大多数情况下,应该使用以下模式
    Lock l = ...;
    l.lock();
     try {
      // access the resource protected by this lock
    } finally {
      l.unlock();
    }}
    
    当锁的获取和释放发生在不同的范围内时,必须小心确保所有在持有锁期间执行的代码都受到try-finally或try-catch的保护,以确保在必要时能够释放锁
    6. Lock接口的实现通过提供以下功能,比使用synchronized方法和语句提供了更多的灵活性:非阻塞尝试获取锁tryLock(), 可以被中断的锁获取尝试 lockInterruptibly,可以设置超时时间的锁获取尝试tryLock(long, TimeUnit).
    7. Lock类还可以提供与隐式监视器锁非常不同的行为和语义,例如保证的顺序、不可重入的使用或死锁检测。如果某个实现提供了这种专门的语义,那么该实现必须在文档中说明这些语义
    8. 请注意,Lock实例只是普通的对象,它们自身可以用作synchronized语句中的目标。获取Lock实例的监视器锁与调用该实例的任何lock方法之间没有明确的关系。为了避免混淆,建议你永远不要以这种方式使用Lock实例,除非是在它们自己的实现中。
    9. 除非另有说明,对任何参数传递null值都将导致抛出NullPointerException

Memory Synchronization

  1. 所有Lock实现必须强制执行与内置监视器锁相同的内存同步语义,如《Java语言规范》第17章所述:
    • 成功的lock操作具有与成功的Lock操作相同的内存同步效果。
    • 成功的unlock操作具有与成功的Unlock操作相同的内存同步效果。
    • 不成功的锁定和解锁操作,以及可重入的锁定/解锁操作,不需要任何内存同步效果

Implementation Considerations

  1. 三种形式的锁获取(可中断的、不可中断的和定时的)可能在性能特性、顺序保证或其他实现质量方面有所不同。此外,中断正在进行(ongoing)的锁获取的能力可能在给定的Lock类中不可用。因此,实现并不需要为所有三种形式的锁获取定义完全相同的保证或语义,也不需要支持对正在进行的锁获取的中断。实现必须清楚地记录每种锁定方法提供的语义和保证。它还必须遵守本接口中定义的中断语义,即在支持锁获取中断的情况下,要么完全支持,要么仅在方法入口处支持
  2. 由于中断通常意味着取消,并且中断检查往往不频繁,因此实现可以优先响应中断而不是正常的方法返回。即使可以证明中断发生在另一个动作可能已经解除线程阻塞之后,这也是正确的。实现应该记录这种行为
  3. 参考:ReentrantLock, Condition,ReadWriteLock , 17.4 Memory Model
public interface Lock {

    /**
     * 获取锁 Acquires the lock.
     * 如果锁不可用,则当前线程将被禁用以进行线程调度,并保持休眠(lies dormant)状态,直到获取到锁为止。
     * 
     * 实现考虑:
     * 一个Lock实现可能能够检测到锁的错误(erroneous )使用,
     * 例如可能导致死锁的调用,并在这种情况下抛出一个(未检查的)异常。
     * 这种情形以及异常类型必须由该Lock实现文档说明。
     *
     */
    void lock();

    /**
     * 
     * 如果当前线程没有被中断,则获取锁
     *
     * 如果锁可用,则立即获取并返回。
     * 如果锁不可用,则当前线程将被禁用以进行线程调度,并保持休眠状态,直到以下两种情况之一发生: 
     * 1. 当前线程获取到锁;或
     * 2. 其他线程中断了当前线程,并且支持中断锁的获取。
     * 
     * 如果当前线程
     * 1. 如果在进入此方法时当前线程的interrupted 状态已被设置,或者
     * 2. 在获取锁的过程中当前线程被中断,并且支持中断锁的获取
     * 则抛出InterruptedException,并且当前线程的中断状态将被清除
     *
     * 实现考虑:
     * 1. 在某些实现中,中断锁的获取可能不可行,即使可行也可能是一个昂贵的操作。
     * 程序员应该意识到这种情况的可能性。 实现应该记录这种情况。
     * 2. 实现可以优先响应中断而不是正常的方法返回。
     * 3.  一个Lock实现可能能够检测到锁的错误使用,例如可能导致死锁的调用,并在这种情况下抛出一个(未检查的)异常。
     * 这种情形以及异常类型必须由该Lock实现文档说明。
     * 
     * @throws InterruptedException 如果当前线程在获取锁的过程中(并且支持中断锁的获取)被interrupted
     */
    void lockInterruptibly() throws InterruptedException;

    /**
     * 仅在调用时锁是空闲的情况下获取锁
     *
     * 如果锁可用,则立即获取并返回true。
     * 如果锁不可用,则立即返回false。
     * 典型用法:
     * 
     * Lock lock = ...;
     * if (lock.tryLock()) {
     *   try {
     *     // manipulate protected state
     *   } finally {
     *     lock.unlock();
     *   }
     * } else {
     *   // perform alternative actions
     * }}
     * 这种用法确保了如果锁被成功获取,则会在finally块中释放锁;如果没有获取到锁,则不会尝试释放锁。
     * 
     * @return 如果锁被成功获取,返回true。否则返回false。
     */
    boolean tryLock();

    /**
     * 在给定的等待时间内获取锁(如果锁是空闲的并且当前线程没有被中断)
     * 如果锁可用,该方法会立即返回true。
     * 如果锁不可用,则当前线程将变为不可调度状态并进入休眠,直到以下三种情况之一发生: 
     * 1. 当前线程获取到锁;
     * 2. 其他线程中断了当前线程,并且支持中断锁的获取;
     * 3. 指定的等待时间已过。
     * 如果锁被成功获取,则返回true
     *
     * 如果当前线程: 
     * 在调用此方法时已经设置了中断状态;或者
     * 在获取锁的过程中被中断,并且支持中断锁的获取, 则抛出InterruptedException异常,并清除当前线程的中断状态。
     * 如果指定的等待时间已过,
     * 则返回false。
     * 
     * 如果等待时间小于或等于零,该方法不会等待。
     * 
     * 实现考虑:
     * 1. 在某些实现中,中断锁的获取可能不可行,即使可行也可能是一个昂贵的操作。
     * 程序员应该意识到这种情况的可能性。 实现应该记录这种情况。
     * 2. 实现可以优先响应中断而不是正常的方法返回或报告超时。
     * 3.  一个Lock实现可能能够检测到锁的错误使用,例如可能导致死锁的调用,并在这种情况下抛出一个(未检查的)异常。
     * 这种情形以及异常类型必须由该Lock实现文档说明。
     *
     *
     * @param time 等待锁的最大时间
     * @param unit time参数的时间单位。
     * @return 如果锁被成功获取,返回true。如果等待时间已过而未能获取到锁,返回false。
     *
     * @throws InterruptedException 如果当前线程在获取锁的过程中(并且支持中断锁的获取)被interrupted
     */
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

    /**
     * 释放锁
     * 实现考虑: 
     * Lock实现通常会对哪个线程可以释放锁进行限制(通常是只有锁的持有者才能释放它),
     * 如果违反了这些限制,可能会抛出一个未检查的异常。
     * 任何限制和异常类型都必须由该Lock实现进行文档说明。
     * 
     */
    void unlock();

    /**
     * 返回一个新的与当前Lock实例绑定的Condition实例
     *
     * 在等待条件之前,当前线程必须持有锁。
     * 
     * 调用Condition#await()方法将原子性地在等待前释放锁,并在等待返回前重新获取锁。
     *
     * 实现考虑: 
     * Condition实例的确切操作取决于Lock的实现,并且必须由该实现进行文档说明。
     *
     * @return 返回一个新的与当前Lock实例关联的Condition实例
     * @throws 如果这个Lock实现不支持条件,则抛出UnsupportedOperationException。
     */
    Condition newCondition();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值