可重入锁之 ReentrantLock

Lock 接口

自Java 5之后,java.util.concurrent.locks 包中的 Lock 接口提供了一种新的方式来实现同步访问。

Lock 接口提供了与 synchronized 类似的同步功能,但需要在使用时手动获取和释放锁。此外,Lock 接口更为灵活,提供了以下 synchronized 接口所不具备的特性:

  • 超时获取锁:在指定时间内获取锁,超过时间仍未获得锁则返回
  • 公平锁:可以通过构造方法 ReentrantLock(boolean fair) 选择是否使用公平锁
  • 响应中断:线程在等待获取锁的过程中可以响应中断,并抛出中断异常
  • 支持绑定多个条件:可以通过绑定 Condition 对象来判断当前线程通知的是哪些线程

Lock 接口中的主要方法:

  • void lock():获取锁。如果锁已被其它线程获取,进行等待
  • void unlock():释放锁
  • boolean tryLock():尝试获取锁。如果获取成功,返回true,否则返回false
  • boolean tryLock(long time, TimeUnit unit) throws InterruptedException:在指定时间内尝试获取锁。如果获取成功,返回true,否则返回false
  • void lockInterruptibly() throws InterruptedException:获取锁。如果锁已被其它线程获取,进行等待。在等待过程中,能够响应中断,中断线程的等待状态
要提醒一点的是,在JDK 5 中,synchronized的性能比较低,但从 JDK1.6 开始,对 synchronized 进行了优化,包括引入的偏向锁、轻量级锁等,性能与 Lock 相差无几。因此建议大家在同样能实现需求的情况下,优先考虑使用 synchronized 进行同步。

重入锁ReentrantLock

Lock接口主要的实现类为重入锁 ReentrantLock。

重入锁的意思可以打个比方:如果你获得了某个房间的钥匙,在还钥匙之前你可以无限次的进入这个房间,synchronized 和 ReentrantLock 都属于可重入锁。

使用示例:

public class RLockDemo {

    //默认构造函数是非公平锁
    Lock lock = new ReentrantLock();

    public void f() {
        lock.lock();
        try {
            System.out.println("时间:" + LocalTime.now().withNano(0));
            TimeUnit.SECONDS.sleep(2);
            System.out.println("hello,world!");
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("时间:" + LocalTime.now().withNano(0));
            System.out.println("==============");
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        RLockDemo demo = new RLockDemo();
        for (int i = 0; i < 2; i++) {
            new Thread(() -> {
                demo.f();
            }).start();
        }
    }
}

输出结果:

时间:21:54:26
hello,world!
时间:21:54:30
==============
时间:21:54:30
hello,world!
时间:21:54:34
==============

可以看到,当第一个线程释放了锁后,第二个线程立刻获得了锁。

注意:采用 Lock 时,必须主动释放锁。因为在发生异常时,不会自动释放锁,因此需要将释放锁的操作放在 finally 块中进行,以保证锁一定会被释放,防止死锁的发生。

参考链接:

猜你喜欢

转载自blog.csdn.net/weixin_43320847/article/details/83189481