Java中的锁

Lock接口

锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源(有些锁可以允许多个线程并发地访问共享资源,比如读写锁)

Java SE5之后,并发包中新增了Lock接口(以及其实现类)来实现锁功能,它提供了与synchronized关键字类似的同步功能,只是在使用的时候需要显示地获取锁和释放锁

虽然缺少了synchronized隐式获取锁的便捷性,但是却拥有了锁获取与释放的可操作性,可中断的获取锁以及超时获取锁等多种synchronized关键字所不具备的同步

1
2
3
4
5
6
Lock lock = new ReentranLock();
lock.lock();
try{
}finally{
lock.unlock();
}

不需要将获取锁的过程写在try中,因为如果在获取锁(自定义锁的实现)时发生了异常,异常抛出的同时.也会导致锁无故释放.

Lock接口提供的synchronized关键字所不具备的主要特性

  • 尝试非阻塞地获取锁

    当前线程尝试获取锁,如果这一时刻锁没有被其他线程获取到,则成功获取并持有锁

  • 能被中断地获取锁

    与synchronized不同,获取到锁的线程能够响应中断,当获取到锁的线程被中断的时候,中断异常将会被抛出,同时锁会被释放

  • 超时获取锁

    在指定的截止时间之前获取锁,如果截止时间到了仍旧无法获取锁,则返回

Lock的API

  • void Lock()

    获取锁,调用该方法当前线程将会获取锁,当锁获得之后,从该方法返回

  • void lockInterruptibly() throws InterruptedException

    可中断地获取锁,和lock()方法的不同之处在于该方法会响应中断,即在锁的获取中可以中断当前线程

  • boolean tryLock()

    尝试非阻塞的获取锁,调用该方法后立刻返回,如果能够获取则返回true,否则返回false

  • boolean tryLock(long time,TimeUnit unit) InterruptedException

    超时的获取锁,当前线程在以下三种情况会返回

    • 当前线程在超时间内获取了锁
    • 当前线程在超时时间内被中断
    • 超时时间结束,返回false
  • void unlock()

    释放锁

  • Condition newCondition()

    获取等待通知组件,该组件与当前的锁绑定,当前线程只有获得了锁,才能调用该组件的wait()方法,而调用后,当前线程将释放锁