java.util.concurrent.locks.Lock详解

简介

java.util.concurrent.locks.Lock接口(以下简称Lock)作者Doug Lea,对比使用synchronized关键字进行并发控制,Lock接口的实现类可以完成更灵活的加锁操作。
本文以下会详细介绍Lock接口相关功能,并对比Lock接口及synchronized关键字在功能上(非性能对比)的异同。

Lock接口相关功能介绍

Lock接口定义6个方法:

  1. lock:尝试获取锁,如当前线程无法获取锁,则当前线程进入无法调度的休眠状态,直到获取锁。
  2. lockInterruptibly: 与 lock相似,主要区别在于调用该方法后,如无法获取锁,则当前线程进入无法调度的休眠状态,直到出现以下两种情况:
    . 获取锁; . 当前线程被其他线程中断。
  3. tryLock: 尝试获取锁,但与lock不同,不会阻塞线程调用后立刻返回,能够获取锁返回true,否则返回false
  4. tryLock(long,TimeUnit): 尝试获取锁,可传入超时参数,在以下3种情况下返回:
    • 在等待时间内获取锁;
    • 在等待时间被其他线程中断,抛出中断异常;
    • 等待时间结束,返回false
  5. unlock:释放锁
  6. newCondition:创建一个Condition对象,此对象另开专题讨论。

Lock接口及synchronized关键字对比

synchronized作为Java语言的并发控制关键字,在多线程编程中十分常用,主要有三种使用方式:

  1. 修饰对象方法;
  2. 修饰静态方法;
  3. 修饰同步方法快。

使用synchronized关键字可以完成对访问共享资源的代码块的显示加锁和隐式释放锁。在代码离开synchronized关键字修饰的区域后,synchronized自动释放锁定,其优势主要为:

  1. JVM内置锁结构,使用简单;
  2. 不需要手动释放,不会出现程序员忘记释放的认为失误;
  3. 可以受到JVM厂商的底层优化。
    其主要缺点为:
    1. 性能一般低于Lock接口的实现类(随着优化的进行,这个性能差距正在极大的缩小);
    2. 灵活性不足,对于较为复杂的加锁操作无法进行支持。

Lock接口将加锁及解锁操作控制权都交给程序员,这增加了锁的灵活性却也增加了出现逻辑问题的可能性。
由此可见,在由于当前synchronized关键字不断得到JVM优化,在仅仅需求简单同步操作时可以优先考虑synchronized关键字,在有灵活加锁操作的需求时再考虑使用Lock接口的各实现类,并且需要谨慎使用,尤其不能忘记锁的释放。

总结

本文主要介绍了Lock接口的各方法含义,并且简单对比了Lock及synchronized关键字的异同。后续计划继续对于synchronized关键字的实现的研究,及Lock接口各典型实现的研究。