一、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. javascript语法之String对象

    学习String类就是学习它的一些方法,主要用到方法全部罗列出来.如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transition ...

  2. javascript语法之函数的定义

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. HTML5进阶(二)HBuilder实现软件自动升级

    HBuilder实现软件自动升级 前言 移动APP开发好后需要实现软件自动升级功能,经过一番搜索,发现HBuilder具有"App资源在线升级更新"的功能,遂研究之. 经过一番测试 ...

  4. android 优化之布局优化

    布局优化的思路很简单,尽量减少布局文件的层级,看过系统源码的都知道,Android view绘制都是逐层绘制的,所以布局的层级少了,decodeview的时候绘制工作自然就少了. 那么如何进行布局的优 ...

  5. 手把手教你画一个 逼格满满圆形水波纹loadingview Android

    才没有完结呢o( ̄︶ ̄)n .大家好,这里是番外篇. 拜读了爱哥的博客,又学到不少东西.爱哥曾经说过: 要站在巨人的丁丁上. 那么今天,我们就站在爱哥的丁丁上来学习制作一款自定义view(开个玩笑,爱 ...

  6. Vim/Vi常用操作(第二版)

    周围同事不是用vim就是Emacs,你要是用一ultraedit,你都不好意思跟人家打招呼;什么插件呀,语法高亮呀,拼写检查呀,能给它开的都给它开着,就是一个字儿:酷. 你说这么牛B一东西,怎么着学会 ...

  7. Linux常用命令(第二版) --压缩解压缩命令

    压缩解压缩命令: ----------.gz---------- 1.压缩 gzip[GNU zip]: /bin/gzip 格式: gzip 选项 [文件] #压缩文件,压缩后扩展名为.gz,Lin ...

  8. LAV Filter 源代码分析 4: LAV Video (2)

    上一篇文章分析了LAV Filter 中的LAV Video的两个主要的类:CLAVVideo和CDecodeThread.文章:LAV Filter 源代码分析 3: LAV Video (1) 在 ...

  9. 基于友善之臂ARM-tiny4412--uboot源码分析

    /* * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core * * Copyright (c) 2004 Texas Instrument ...

  10. Unity修改Particles Render Material(Unity3D开发之二十三)

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/48372999 ...