一、ReentrantLock简介

  ReentrantLock字面意义上理解为可重入锁。那么怎么理解可重入这个概念呢?或者说和我们经常用的synchronized又什么区别呢?

  ReentrantLock可重入锁是一种递归无阻塞的同步锁机制,简单意思就是说可重入锁就是当前持有该锁的线程能够多次获取该锁,无需等待。它可以等同于synchronized的作用,但是它比synchronized更加的灵活,更加的强大,能够更好的降低死锁发生的概率。

二、ReentrantLock使用和Lock接口中的API介绍

  2.1、构造方法

  ReentrantLock是lock接口的实现类。

  无参数构造。直接返回ReentrantLock锁的实例。

  有参数构造。支持传入一个boolean类型的参数表示这个锁是公平锁还是非公平锁。ReentrantLock默认是非公平锁。设置参数为true表示为公平锁。

  2.2、lock()方法

  lock方法表示当前线程去获取锁。不能获取到锁则等待。需要注意的是ReentrantLock锁需要我们手动的释放锁,必须主动去释放锁,并且在发生异常时,不会自动释放锁。因此一般来说,使用Lock必须在try{}catch{}块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被被释放,防止死锁的发生。

  

         ReentrantLock lock = new ReentrantLock();
lock.lock();//获取锁
try{
//处理业务
}catch (Exception e){ }finally {
lock.unlock();//释放锁
}

  2.3、tryLock()方法

  由于lock方法获取锁以后只能一直等待。这样有些不太友好。提供了tryLock方法。该方法会提供一个boolean返回值。为true表示获取锁成功,为false则表示获取锁失败了。这样可以避免一直无脑的等待锁。同时tryLock提供了一个重载方法tryLock(long time, TimeUnit unit)。tryLock(long time, TimeUnit unit)方法和tryLock()方法是类似的,只不过区别在于这个方法在拿不到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false。如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。

         if (lock.tryLock()){
try {
//得到锁 处理业务
} catch(Exception e){ } finally {
lock.unlock();
}
}else{
//没有获取到锁,先执行其他的任务
}

  2.4、lockInterruptibly()方法。响应中断操作

  当通过这个锁去获取锁的时候可以响应的中断操作,意思就是当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假若此时线程A获取到了锁,而线程B只有在等待,那么对线程B调用threadB.interrupt()方法能够中断线程B的等待过程。这个过程叫做中断自己,会捕获到InterruptedException异常。注意,当一个线程获取了锁之后,是不会被interrupt()方法中断的。

三、ReentrantLock类简单使用

  前面有说了该类主要是更加灵活的使用synchronized同步锁。

 

 import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock; public class TestReentrantLock {
public static List<Integer> list = new ArrayList<>();
public ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
TestReentrantLock addThread = new TestReentrantLock();
new Thread(){
public void run(){
//addThread.insert(Thread.currentThread());
addThread.tryInsert(Thread.currentThread());
}
}.start(); new Thread(){
public void run(){
//addThread.insert(Thread.currentThread());
addThread.tryInsert(Thread.currentThread());
}
}.start();
} /**
* 只有一个线程能够对list集合进行增加操作
*/
public void insert(Thread thread){ lock.lock();
try{
System.out.println("当前线程:"+thread.getName()+"获取了锁");
for (int i = 0;i < 10;i++){
list.add(i);
}
}catch (Exception e){ }finally {
System.out.println("当前线程:"+thread.getName()+"释放了锁");
lock.unlock();
} } /**
* 尝试插入数据。如果当前不让插入数据。则去做其他业务
* @param thread
*/
public void tryInsert(Thread thread){
if (lock.tryLock()){
try{
System.out.println("当前线程:"+thread.getName()+"获取了锁");
for (int i = 0;i < 10;i++){
list.add(i);
}
}catch (Exception e){ }finally {
System.out.println("当前线程:"+thread.getName()+"释放了锁");
lock.unlock();
}
}else{
System.out.println("线程"+thread.getName()+"获取锁失败");
}
} }
线程Thread-1获取锁失败
当前线程:Thread-0获取了锁
当前线程:Thread-0释放了锁

四、(Lock接口)ReentrantLock和synchronized的一些比较

  4.1、Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现。

  4.2、synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁。

  4.3、Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断。

  4.4、通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。

  

 

Java并发之ReentrantLock的更多相关文章

  1. java并发之ReentrantLock学习理解

    简介 java多线程中可以使用synchronized关键字来实现线程间同步互斥,但在jdk1.5中新增加了ReentrantLock类也能实现同样的效果,并且在扩展功能上也更加强大,比如具有嗅探锁定 ...

  2. Java并发之ReentrantLock详解

    一.入题 ReentrantLock是Java并发包中互斥锁,它有公平锁和非公平锁两种实现方式,以lock()为例,其使用方式为: ReentrantLock takeLock = new Reent ...

  3. Java并发之ReentrantLock源码解析(一)

    ReentrantLock ReentrantLock是一种可重入的互斥锁,它的行为和作用与关键字synchronized有些类似,在并发场景下可以让多个线程按照一定的顺序访问同一资源.相比synch ...

  4. Java并发之ReentrantLock源码解析(二)

    在了解如何加锁时候,我们再来了解如何解锁.可重入互斥锁ReentrantLock的解锁方法unlock()并不区分是公平锁还是非公平锁,Sync类并没有实现release(int arg)方法,这里会 ...

  5. Java并发之ReentrantLock源码解析(三)

    ReentrantLock和BlockingQueue 首先,看到这个标题,不要怀疑自己进错文章,也不要怀疑笔者写错,哈哈.本章笔者会从BlockingQueue(阻塞队列)的角度,看看juc包下的阻 ...

  6. Java并发之ReentrantLock源码解析(四)

    Condition 在上一章中,我们大概了解了Condition的使用,下面我们来看看Condition再juc的实现.juc下Condition本质上是一个接口,它只定义了这个接口的使用方式,具体的 ...

  7. JAVA并发之阻塞队列浅析

    背景 因为在工作中经常会用到阻塞队列,有的时候还要根据业务场景获取重写阻塞队列中的方法,所以学习一下阻塞队列的实现原理还是很有必要的.(PS:不深入了解的话,很容易使用出错,造成没有技术深度的样子) ...

  8. java并发之CopyOnWirteArrayList

    java并发之CopyOnWirteArrayList CopyOnWirteArrayList的实现 它用了ReentrantLock保证了add,set,remove操作的安全,同时使用volat ...

  9. Java并发之显式锁和隐式锁的区别

    Java并发之显式锁和隐式锁的区别 在面试的过程中有可能会问到:在Java并发编程中,锁有两种实现:使用隐式锁和使用显示锁分别是什么?两者的区别是什么?所谓的显式锁和隐式锁的区别也就是说说Synchr ...

随机推荐

  1. (NO.00002)iOS游戏精灵战争雏形(四)

    在Xcode打开MainScene,添加初始化代码如下: -(void)didLoadFromCCB{ NSAssert(_sprite1, @"_sprite1 must not nil& ...

  2. OS X 10.11 中的安全删除文件

    在 OS X 10.11 中安全倾倒垃圾桶这个功能已经被取消了.是因为 SSD 闪存硬盘的原因 . 安全删除操作并不能安全清除. 所以就直接取消了. 但是其实其实还是可以在系统内使用安全删除功能的. ...

  3. LeetCode之“链表”:在O(1)时间删除链表节点

    下边讨论暂不包括尾节点. 一般来说,我们要删除链表中的一个节点是需要知道其上一节点的.但我们真的需要吗? 其实我们可以将待删节点的下一节点的值和指向的下一节点赋予待删节点,然后删除待删节点的下一节点. ...

  4. 队列顺序存储 - 设计与实现 - API函数

    队列是一种特殊的线性表 队列仅在线性表的两端进行操作 队头(Front):取出数据元素的一端 队尾(Rear):插入数据元素的一端 队列不允许在中间部位进行操作! queue常用操作 销毁队列 清空队 ...

  5. web报表工具FineReport使用中遇到的常见报错及解决办法(二)

    web报表工具FineReport使用中遇到的常见报错及解决办法(二) 这里写点抛砖引玉,希望大家能把自己整理的问题及解决方法晾出来,Mark一下,利人利己. 出现问题先搜一下文档上有没有,再看看度娘 ...

  6. SharePoint 2010 之soap:Server服务器无法处理请求

    算是一个下马威?!刚刚部署上的SharePoint2010环境,感觉很欣喜,开始操作,结果装上Designer2010,打开页面,居然报错 错误内容:soap:Server服务器无法处理请求. --- ...

  7. 解决idea的项目启动报404的问题

    最近在学习IDEA,由于之前一直使用的是Eclipse,所以初次接触IDEA就接触到了不少的坑,其中最让人头疼的大概就是如何让IDEA顺利的启动起来了,这方面我就不细讲了,网上已经有了不少的教程,稍后 ...

  8. 14.QT-QFile文件,QBuffer缓冲区,QDir目录,QFileSystemWatcher文件系统监视

    QFile Qt中所有与IO相关的类都继承于QIODevice,继承图如下所示: 其中QFile类便是用于文件操作的类 在QT中,将文件当做一种特殊的外部设备对待(比如:串口,usb等就是外部设备) ...

  9. 白瑜庆:知乎基于Kubernetes的kafka平台的设计和实现

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文首发在云+社区,未经许可,不得转载. 自我介绍 我是知乎的技术中台工程师,现在是负责知乎的存储相关组件.我的分享主要基于三个,一个是简单 ...

  10. Jquery的过滤选择器分为哪几种?

    Jquery的过滤选择器分为哪几种? 转载▼ 标签: jquery 过滤选择器 分类 分类: JQuery 所有的过滤选择器分为哪几种: 一.基本过滤选择器(重点掌握下列八个) :first 选取第一 ...