简介

ReentrantLock(重入锁)就是支持可重进入的锁,它表示该锁能支持一个线程对资源的重复加锁。另外还支持获取锁的公平和非公平选择ReentrantLock的实现不仅可以替代隐式的synchronized关键字,而且还能够提供超过关键字本身的多种功能。

公平与非公平

这个概念是针对锁的获取的,在绝对时间上,先对锁进行获取的请求一定先满足,那么这个锁是公平的,反之就是不公平的。公平锁的获取就是等待时间最长的线程最先获取锁,也就是锁获取是顺序的。但是公平锁的机制往往效率不高。

ReentrantLock的调用过程

ReentrantLock把所有Lock接口的操作都委派到一个sync类上,该类继承了队列同步器:

static abstract class Sync extends AbstractQueuedSynchronizer {
final static class NonfairSync extends Sync
final static class FairSync extends Sync

1、sync有两个子类,分别实现的是公平锁和非公平锁,默认为非公平锁。

2、由于该同步组件的实现使用的模板方法模式,我们看下ReentrantLock.lock()方法的调用过程(默认为非公平锁)

非公平锁语义

final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}

1、首先判断锁当前的状态,如果锁空闲,则当前线程尝试获取。

2、当前线程获取锁成功,则设置当前线程为锁的拥有者。

3、如果锁状态为非空闲状态且当前线程为锁的拥有者,则直接将同步状态值进行增加并返回true,表示获取同步状态成功。

这里就是支持锁重入的场景,跟synchronized类似:成功获取锁的线程再次获取锁,只是增加了同步状态值,与此对应的是,在释放锁的时候需要对应减少同步状态值,直到同步状态值为0的时候,才表示这把锁真正的被释放了。

protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}

公平锁语义

 protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (isFirst(current) &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}

这里与非公平锁大部分地方类似,只是线程在获取同步状态时,需要判断当前节点的前驱节点是否为首节点。公平锁总是按照队列的顺序来来获取锁的。

ReentrantLock的使用场景

1、发现该操作已经在执行中则不再执行

a、用在定时任务时,如果任务执行时间可能超过下次计划执行时间,确保该任务只有一个正在执行,忽略重复触发。

b、用在界面交互时点击执行较长时间请求操作时,防止多次点击导致后台重复执行。

主要用于进行非重要任务时防止重复执行。

private ReentrantLock lock = new ReentrantLock();

    public void test()
{
if(lock.tryLock())
{
try
{
//dosomothing
}
finally
{
lock.unlock();
}
}
}

2、如果该操作已经在执行,则等待一个个执行(同步执行,与synchronized类似)

3、如果该操作已经在执行,则尝试等待一段时间,超时则放弃执行

 if(lock.tryLock(5, TimeUnit.SECONDS))
{
try
{
//dosomothing
}
finally
{
lock.unlock();
}
}

这种其实属于场景2的改进,等待获得锁的操作有一个时间的限制,如果超时则放弃执行。
用来防止由于资源处理不当长时间占用导致死锁情况(大家都在等待资源,导致线程队列溢出)。

场景4:如果发现该操作已经在执行,等待执行。这时可中断正在进行的操作立刻释放锁继续下一操作。

synchronized与Lock在默认情况下是不会响应中断(interrupt)操作,会继续执行完。lockInterruptibly()提供了可中断锁来解决此问题。(场景2的另一种改进,没有超时,只能等待中断或执行完毕)

ReentrantLock的实现语义与使用场景的更多相关文章

  1. 灵魂代码分享HTML元素标签语义化及使用场景实用到爆

    灵魂三问: 标签语义化是什么?为什么要标签语义化?标签语义化使用场景有哪些? 下面让我们跟着这三个问题来展开一下本文的内容. 一.标签语义化是什么? 标签语义化就是让元素标签做适当的事情.例如 p 标 ...

  2. ECCV 2018 | 旷视科技提出统一感知解析网络UPerNet,优化场景理解

    全球计算机视觉三大顶会之一 ECCV 2018(European Conference on Computer Vision)即将于 9 月 8 -14 日在德国慕尼黑拉开帷幕.届时,旷视首席科学家孙 ...

  3. CVPR2020:4D点云语义分割网络(SpSequenceNet)

    CVPR2020:4D点云语义分割网络(SpSequenceNet) SpSequenceNet: Semantic Segmentation Network on 4D Point Clouds 论 ...

  4. PyTorch中的MIT ADE20K数据集的语义分割

    PyTorch中的MIT ADE20K数据集的语义分割 代码地址:https://github.com/CSAILVision/semantic-segmentation-pytorch Semant ...

  5. ReentrantLock可重入锁——源码详解

    开始这篇博客之前,博主默认大家都是看过AQS源码的~什么居然没看过猛戳下方 全网最详细的AbstractQueuedSynchronizer(AQS)源码剖析(一)AQS基础 全网最详细的Abstra ...

  6. 快进来!花几分钟看一下 ReentrantReadWriteLock 的原理!

    前言 在看完 ReentrantLock 之后,在高并发场景下 ReentrantLock 已经足够使用,但是因为 ReentrantLock 是独占锁,同时只有一个线程可以获取该锁,而很多应用场景都 ...

  7. Java并发包源码学习系列:阻塞队列BlockingQueue及实现原理分析

    目录 本篇要点 什么是阻塞队列 阻塞队列提供的方法 阻塞队列的七种实现 TransferQueue和BlockingQueue的区别 1.ArrayBlockingQueue 2.LinkedBloc ...

  8. LMAX Disruptor—多生产者多消费者中,消息复制分发的高性能实现

    解决的问题 当我们有多个消息的生产者线程,一个消费者线程时,他们之间如何进行高并发.线程安全的协调? 很简单,用一个队列. 当我们有多个消息的生产者线程,多个消费者线程,并且每一条消息需要被所有的消费 ...

  9. Fully Convolutional Networks for semantic Segmentation(深度学习经典论文翻译)

    摘要 卷积网络在特征分层领域是非常强大的视觉模型.我们证明了经过端到端.像素到像素训练的卷积网络超过语义分割中最先进的技术.我们的核心观点是建立"全卷积"网络,输入任意尺寸,经过有 ...

随机推荐

  1. 蒟蒻修养之cf橙名计划2

    29 由于第一篇没写题意导致大部分神题题解已经完全不知道在说啥了...所以还是重开一篇保平安... [303A]题意:求三个长度为$n(n<=10^5)$的排列$a,b,c$使得$a_i+b_i ...

  2. 【BZOJ2438】 [中山市选2011]杀人游戏 tarjan强连通分量+缩点

    Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是 ...

  3. 每日英語2013.09.09(Email常用單字)

    carbon copy 副本抄送 forward 轉交;轉寄(+to) Please check the file carried by this email for the details.細節請看 ...

  4. Centos 下安装Docker 遇到的一些错误

    1.公司的服务器的内核版本:2.6.32-431.23.3.el6_x86_64 如何升级内核请参考前一篇文章 2.在这个地址上面下载 的 https://test.docker.com/builds ...

  5. Hibernate学习笔记2

    hibernate.cfg.xml文件配置中: <property name="hibernate.hbm2ddl.auto">update</property& ...

  6. 用GruntJS合并、压缩JS文件

    为什么要合并.压缩你的JS文件?        一个项目开发完成我们总能发现有一堆js文件非常混乱.           一般在一个HTML文档加载的时候,浏览器会根据HTML代码从上到下读取所需要加 ...

  7. [LintCode] Valid Palindrome 验证回文字符串

    Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignori ...

  8. HTML5初学篇章_4

    HTML5的表单所有type类型(补第一章) 类型 说明 button 定义可点击的按钮(大多与 JavaScript 使用来启动脚本) checkbox 定义复选框. color 定义拾色器. da ...

  9. ss命令

    看到好的博文,所以记录一下.本文出自转载. ss是Socket Statistics的缩写.顾名思义,ss命令可以用来获取socket统计信息,它可以显示和netstat类似的内容.但ss的优势在于它 ...

  10. js打开没有地址栏下拉条新窗口

    <script type="text/javascript" language="javascript"> function vNodeAuditL ...