简介
java.util.concurrent.locks.Lock接口(以下简称Lock)作者Doug Lea,对比使用synchronized关键字进行并发控制,Lock接口的实现类可以完成更灵活的加锁操作。
本文以下会详细介绍Lock接口相关功能,并对比Lock接口及synchronized关键字在功能上(非性能对比)的异同。
Lock接口相关功能介绍
Lock接口定义6个方法:
- lock:尝试获取锁,如当前线程无法获取锁,则当前线程进入无法调度的休眠状态,直到获取锁。
- lockInterruptibly: 与 lock相似,主要区别在于调用该方法后,如无法获取锁,则当前线程进入无法调度的休眠状态,直到出现以下两种情况:
. 获取锁; . 当前线程被其他线程中断。 - tryLock: 尝试获取锁,但与lock不同,不会阻塞线程调用后立刻返回,能够获取锁返回true,否则返回false
- tryLock(long,TimeUnit): 尝试获取锁,可传入超时参数,在以下3种情况下返回:
- 在等待时间内获取锁;
- 在等待时间被其他线程中断,抛出中断异常;
- 等待时间结束,返回false
- unlock:释放锁
- newCondition:创建一个Condition对象,此对象另开专题讨论。
Lock接口及synchronized关键字对比
synchronized作为Java语言的并发控制关键字,在多线程编程中十分常用,主要有三种使用方式:
- 修饰对象方法;
- 修饰静态方法;
- 修饰同步方法快。
使用synchronized关键字可以完成对访问共享资源的代码块的显示加锁和隐式释放锁。在代码离开synchronized关键字修饰的区域后,synchronized自动释放锁定,其优势主要为:
- JVM内置锁结构,使用简单;
- 不需要手动释放,不会出现程序员忘记释放的认为失误;
- 可以受到JVM厂商的底层优化。
其主要缺点为:- 性能一般低于Lock接口的实现类(随着优化的进行,这个性能差距正在极大的缩小);
- 灵活性不足,对于较为复杂的加锁操作无法进行支持。
Lock接口将加锁及解锁操作控制权都交给程序员,这增加了锁的灵活性却也增加了出现逻辑问题的可能性。
由此可见,在由于当前synchronized关键字不断得到JVM优化,在仅仅需求简单同步操作时可以优先考虑synchronized关键字,在有灵活加锁操作的需求时再考虑使用Lock接口的各实现类,并且需要谨慎使用,尤其不能忘记锁的释放。
总结
本文主要介绍了Lock接口的各方法含义,并且简单对比了Lock及synchronized关键字的异同。后续计划继续对于synchronized关键字的实现的研究,及Lock接口各典型实现的研究。