一、前言
锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源。在lock接口出现之前程序是靠synchronized关键字实现锁功能,lock接口提供了与synchronized关键字类似的同步功能,只是在使用的过程中需要显示的获取和释放锁。
- 缺点:缺少隐士获取释放锁的便捷性。
- 优点:拥有锁获取与释放的可操作性,可中断的获取硕=锁以及超市获取锁等特性。
二、方法注释翻译
① void lock()方法。
/**
* 获得锁。
* 如果锁不可用,则当前线程将出于线程调度目的而禁用,并处于休眠状态,直到获得锁为止。
*
* 实现注意事项:
* 锁实现可能能够检测锁的错误使用,例如导致死锁的调用,并可能在这种情况下抛出(未选中的)异常。该锁实现必须记录环境和异常类型。
*/
void lock();
描述:获取锁,调用该方法线程将会获取锁,当获取锁后,从该方法返回,若获取不到锁则阻塞。
② void lockInterruptibly() throws InterruptedException方法。
/**
* 获取锁,除非当前线程正在链接普通线程中断。
* 如果锁可用,则获取锁并立即返回。
*
* 如果锁不可用,那么当前线程将出于线程调度的目的被禁用,并处于休眠状态,直到发生以下两种情况之一:
* 1.锁被当前线程获取;
* 2.其他一些线程连接普通线程中断当前线程,支持中断锁获取。
*
* 如果当前线程:
* 1.在进入此方法时已设置其中断状态;
* 2.或者是在获取锁的过程中,linkplain线程被中断,并且支持获取锁的中断,然后抛出link InterruptedException并清除当前线程的中断状态。
*
* 实现注意事项:
* 1.在某些实现中中断锁获取的能力可能是不可能的,而且如果可能的话,这可能是一个昂贵的操作。程序员应该意识到情况可能是这样的。在这种情况下,实现应该记录。
* 2.实现可能更倾向于响应中断而不是正常的方法返回。
* 3.锁实现可能能够检测锁的错误使用,例如导致死锁的调用,并可能在这种情况下抛出(未选中的)异常。该锁实现必须记录环境和异常类型。
* @throws InterruptedException
*/
void lockInterruptibly() throws InterruptedException;
描述:可中断获取锁,和lock方法的不同之处在于该方法会响应中断,即在锁的获取中可以中断当前线程。
③ boolean tryLock()方法。
/**
* 仅当锁在调用时处于空闲状态时才获取锁。
* 如果锁可用,则获取锁并立即返回值true。
* 如果锁不可用,则此方法将立即返回值false。
* 这种用法确保锁在被获取时被解锁,而在未被获取时不会尝试解锁。
* @return
*/
boolean tryLock();
描述:尝试非阻塞的获取锁,调用该方法立即返回,如果能够获取在返回true,否则返回true
④ boolean tryLock(long time, TimeUnit unit) throws InterruptedException方法。
/**
* 如果在给定的等待时间内线程是空闲的,并且当前线程没有被链接,则获取锁。
*
* 如果锁可用,则此方法立即返回值true。
* 如果锁不可用,那么当前线程将出于线程调度的目的而被禁用,并处于休眠状态,直到发生以下三种情况之一:
* 1.锁被当前线程获取;
* 2.其他线程连接普通线程中断当前线程,支持中断锁获取;
* 3.指定的等待时间已经过了
* 如果获得锁,则返回true值。
*
* 如果当前线程:
* 1.在进入此方法时已设置其中断状态;
* 2.当获取锁时,为linkplain线程中断,且支持锁获取中断,则抛出link InterruptedException并清除当前线程的中断状态。
* 如果指定的等待时间过期,则返回false值。
* 如果时间小于或等于0,则该方法根本不会等待。
*
* 实现注意事项
* 1.在某些实现中中断锁获取的能力可能是不可能的,而且如果可能的话,这可能是一个昂贵的操作。
* 2.程序员应该意识到情况可能是这样的。在这种情况下,实现应该记录。
* 3.实现可能更倾向于响应中断而不是正常的方法返回,或者报告超时。
* 4.锁实现可能能够检测锁的错误使用,例如导致死锁的调用,并可能在这种情况下抛出(未选中的)异常。该锁实现必须记录环境和异常类型。
* @param time
* @param unit
* @return
* @throws InterruptedException
*/
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
描述:超时获取锁,当前线程在以下3中情况下会返回:
1、当前线程在超时时间内获取了锁
2、当前线程在超时时间内被中断
3、超时时间结束,返回false
⑤ void unlock()方法。
/**
* 释放锁。
*
* 实现注意事项
* 锁实现通常会对哪个线程可以释放锁施加限制(通常只有锁的持有者可以释放锁),
* 如果违反了限制,可能会抛出(未选中的)异常。任何限制和异常类型都必须由锁实现记录下来。
*/
void unlock();
描述:释放锁。
⑥ Condition newCondition()。
/**
* 返回绑定到此锁实例的新条件实例。
* 在等待条件之前,锁必须由当前线程持有。
* 对条件的调用将在等待之前自动释放锁,并在等待返回之前重新获取锁。
*
* 实现注意事项
* 条件实例的确切操作取决于锁实现,并且必须由该实现记录。
* @return
*/
Condition newCondition();
描述:获取等待通知组件,该组件和当前锁绑定,当前线程只有获取了锁,才能调用该组件的wait()方法。调用后,当前线程将释放锁。
三、总结
在Lock接口出现之前,Java程序是靠synchronized关键字实现锁功能的,而Java SE 5之后,并发包中新增了Lock接口(以及相关实现类)用来实现锁功能,它提供了与synchronized关键字类似的同步功能,只是在使用时需要显式地获取和释放锁。虽然它缺少了(通过synchronized块或者方法所提供的)隐式获取释放锁的便捷性,但是却拥有了锁获取与释放的可操作性、可中断的获取锁以及超时获取锁等多种synchronized关键字所不具备的同步特性。