一、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.00001)iOS游戏SpeedBoy Lite成形记(二十二)

    自己的游戏自己更需要多玩,这样才能首先发现不足的地方.所以本猫到现在已经忍一个地方很久了,就是弹出moneyLayer后每次都要输入数字才能关闭,这多少让人不爽.于是本篇我们就修正这个小小的不便. 首 ...

  2. Hive 配置

    <?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="confi ...

  3. Android开源项目——设置图文居中的按钮 IconButton

    本文介绍一下一个小众的开源项目--IconButton. 本文原创,转载请注明出处: http://blog.csdn.net/maosidiaoxian/article/details/435602 ...

  4. JSONP获取Twitter和Facebook文章数

    原文链接: Retrieve Twitter and Facebook Counts with JSON 翻译人员: 铁锚 原文日期: 2014年02月19日 翻译日期: 2014年02月22日 !! ...

  5. 算法精解:最小二乘法C实现

    计量经济学研究的直接目的是确定总体回归函数Yi=B1+B2Xi+ui,然而能够得到的只是来自总体的若干样本的观测值,要用样本信息建立的样本回归函数尽可能"接近"地去估计总体回归函数 ...

  6. 数据cube的schema与sql的对应的关系

    用schema workbench 设置cube的维度结构 saiku 使用的cube,会将不同维度的查询转化为sql语句. schema中, cube的事实表和dimension表进行自然连接,具体 ...

  7. C/C++中关键字static的用法及作用

    本文将主要从static在C和C++共有的作用及C++特有的作用两个方面进行解析. 在C和C++中共有的作用 隐藏(对变量.函数均可) 当同时编译多个文件时,所有未加static前缀的全局变量或全局函 ...

  8. RTMPdump(libRTMP) 源代码分析 6: 建立一个流媒体连接 (NetStream部分 1)

    ===================================================== RTMPdump(libRTMP) 源代码分析系列文章: RTMPdump 源代码分析 1: ...

  9. SharePoint 调用WebService操作List小记

    简述:在SharePoint的使用中,经常需要进行系统集成这样的操作,我们作为SharePoint开发,就需要给其他系统提供接口,而SharePoint提供的WebService就很好的提供了这样的功 ...

  10. (WPS) 网络地理信息处理服务

    WPS 标准为网络地理信息处理服务提供了标准化的输入和输出. OGC® Web Processing Service (WPS) 标准描述了如何通过远程的任何算法和模型处理获得地理空间的栅格或矢量信息 ...