-
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(); }
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
- 另请参见:
-
ReentrantLock
,Condition
,ReadWriteLock
- 成功的
-
-
方法摘要
所有方法 实例方法 抽象方法 变量和类型 方法 描述 void
lock()
获得锁。void
lockInterruptibly()
除非当前线程是 interrupted,否则获取锁定。Condition
newCondition()
返回一个新Condition
绑定到该实例Lock
实例。boolean
tryLock()
只有在调用时它是空闲的才能获取锁。boolean
tryLock(long time, TimeUnit unit)
如果锁在给定的等待时间内是空闲的并且当前线程不是 interrupted ,则获取锁。void
unlock()
释放锁定。
-
-
-
方法详细信息
-
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
实施不支持条件
-
-