Java并发编程中的ReentrantLock类详解
目录
- 一、ReentrantLock介绍
- 二、ReentrantLock特性详解
- 1. 多条件队列
- 2. 非公平 & 公平锁
- 3. 可中断
- 4. 超时
- 5. 轮询
- 三、ReentrantLock类和synchronized关键字的区别
一、ReentrantLock介绍
ReentrantLock是juc.locks包中的一个独占式可重入锁,相比synchronized,它可以创建多个条件等待队列,还支持公平/非公平锁、可中断、超时、轮询等特性。
ReentrantLock实现Lock接口实现了一个锁所需的方法,如lock()、unLock()等,在这些方法中实际上是调用继承了AQS的同步器Sync对象中的方法来实现对锁资源的获取与释放,而内部类Sync有两个子类FairSync和NonfairSync,分别对应公平锁和非公平锁。ReentrantLock默认构造器是构造非公平锁
二、ReentrantLock特性详解
1. 多条件队列
Sync对象中开放了创建AQS中条件队列ConditionObject对象的方法,并重写了isHeldExclusively()方法(通知方法signal()要用到),因此可创建条件队列实现通知等待机制。
2. 非公平 & 公平锁
非公平锁NonfaiandroidrSync 新进来的线程会先直接与同步队列中的线程竞争CAS竞争失败则调用acquire -> tryAcquire -> nonfairTryAcquire继续竞争,再失败才会在acquire方法中后续执行加入同步队列若线程是重入这个锁,会记录重入次数,若超过int范围溢出则抛出错误
公平锁FairSync 新来的线程若同步队列为空才竞争锁,否则tryAcquire直接返回false然后进入队列排队,实现先来后到公平锁同样也会记录重入次数
3.android 可中断
我们知道synchronized在锁竞ltYMrXlQMk争时是不可中断的,获取不到锁的线程会一直处于阻塞状态。
而ReentrantLock调用lockInterruptibly()获取锁的过程是可以响应中断的,其内部调用的是AQS的acquireInterruptibly()方法
当收到中断信号时会退出阻塞然后抛出InterruptedException异常从而退出锁竞争。
4. 超时
js调用tryLock(long timeout, TimeUnit unit)获取锁可实现超时功能,当超过时间还未获取到锁则直接抛出异常退出锁竞争
内部是AQS中调用LockSupport.parkNanos()超时阻塞实现的
5. 轮询
ReentrantLock的轮询特性是指可通过tryLock()方法尝试获取锁,没获取到则不阻塞直接退出,可以过会再来尝试。tryLock()调用Sync中定义的nonfairTryAcquire方法,从前面列出的源码可知没获取到则直接返回false
三、www.devze.comReentrantLock类和synchronized关键字的区别
ReentrantLock和synchronized都是独占式可重入锁,但是它们有如下区别:
- 锁实现机制:ReentrantLock是一个类,是基于AQS实现的,依赖于JDK的API;synchronized是一个关键字,是直接在JVM层面通过监视器实现的锁机制。
- 条件等待队列:ReentrantLock通过Condition可创建多个条件等待队列;而synchronized依赖的监视器模型中只有一个等待队列。
- 非公平 & 公平锁:ReentrantLock支持公平和非公平锁;synchronized为非公平锁
- 其他特性:ReentrantLock还支持可中断、超时、轮询等特性;synchronized不支持这些
- 底层原理:ReentrantLock是基于CAS实现共享资源同步,synchronized底层是基于互斥量实现的
一般来说在不需要用到ReentrantLock特殊特性的时候就用synchronized,因为synchronized显然相对来说使用起来更加简洁高效
到此这篇关于Java并发编程中的ReentrantLock类详解的文章就介绍到这了,更多相关Java的ReentrantLock类内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论