ReentrantLock实现机制
掌握Reentrantlock
具体结构
下文Reentrantlock简称RL,阅读之前强烈建议读一下AQS源码解析: https://www.cnblogs.com/seamount3/p/18690818
其实RL和AQS有关系,但不是直接有关系,是RL内部有一个Sync变量,RL其实是实现LOCK接口好来实现对应的LOCK方法
何为Sync,其实是一个内部类 extends AQS,内部又有两个子类分别是公平锁与非公平锁
RL的核心就是在对应的内部类Sync的子类上
子类之FairSync
lock
final void lock() {
acquire(1);
}
没太多好说的,其实就只是包装了一下,调用AQS的 acquire方法
相对有意思的就是为什么要是1?
1其实是AQS抽象出来的参数,在此地是代表线程请求锁时需要获取的许可数量
这里的 1 表示当前线程请求 一个 锁的许可,锁的操作是以许可为基础的。
具体看下面的tryAcquire
tryAcquire
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
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;
}
}
相对简单,流程如下:
- 获取当前state变量
- state=0,判断CLH是否有节点
- 如果没有那么进行CAS操作state
- 操作成功的话,设置为独占线程
- state=0,判断CLH是否有节点
- 为了实现可重入,那么还要考虑是否独占线程为当前线程
- 是的话,int nextc = c + acquires;并且setState
子类之NonfairSync
lock
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
tryAcquire
一样不赘述
Sync父类实现了什么功能?
核心之tryRelease
本方法的实现是为了给AQS实现对应的钩子方法,在RL的unlock方法最终会调用AQS的release
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;
}
核心的流程如下:
- 判断当前线程是否是锁资源持有的线程
- 不是的话,抛异常
- 1ok后,修改state
- 如果state改完==0,那么彻底释放锁
- 如果不等于只是修改state,不释放锁,为了支持可重入嘛
如果面试官让介绍ReentrantLock如何介绍?
- 快速简单介绍(包括功能)
- 详细介绍下如何实现
快速简单介绍(包括功能)
首先ReentrantLock实现了对应的Lock接口,他的功能基本上起到的就是本地锁的作用,
ReentrantLock在功能上支持:
- 互斥性(RL是互斥锁,同一时刻只允许一个线程获取锁进入临界区,写操作自然也是互斥的。)
- 可重入性
- 公平与非公平
- 可中断,
lockInterruptibly()方法,允许线程在等待锁的过程中被中断 - 限时性,例如TryLock可以允许线程在指定的时间内尝试获取锁。如果在指定时间内没有获取到锁,线程会返回
false。
上述的功能大多是借助AQS的已有代码,以及ReentrantLock内部类像FairSync等继承了AQS并且实现了对应的钩子方法例如tryAcquire来实现总体的功能
详细介绍下如何实现
讲一下lock流程:
- 首先入口是RL的lock方法,而底层其实是调用内部变量Sync的acquire方法(也就是AQS的acquire模板方法)
- 这里就体现出公平与非公共的区别了,在构造器中我们会生成公平锁的实例或者非公平锁的实例通过这一点就实现了公平与非公平
- 以公平为例,那么我们会进行AQS的acquire流程
- 先调用对应公平锁实现的tryAcquire
- 获取当前state变量
- state=0,判断CLH是否有节点
- 如果没有那么进行CAS操作state
- 操作成功的话,设置为独占线程
- state=0,判断CLH是否有节点
- 为了实现可重入,那么还要考虑是否独占线程为当前线程
- 是的话,int nextc = c + acquires;并且setState
- 获取当前state变量
- 先调用对应公平锁实现的tryAcquire
- 如果tryAcquire失败,那么就进入把当前线程转换为Node添加到CLH队尾流程,然后等待唤醒,然后对应还有一个重要的方法就是acquireQueued,相当于是死循环,然后每个线程会再次tryAcquire如果失败再阻塞,之后就等待唤醒
讲一下unlock流程:
- 内部会调用对应Sync类的release方法(也就是AQS实现的模板方法)
- 然后执行对应的tryRelease流程
- 最后唤醒队列中的下一个节点
而刚刚提到的可中断也是AQS锁支持的,以及超时机制,都是AQS在特定代码,例如可中断则是在循环中会去判断下线程状态而超时则是在循环过程中结合当前时间与起始时间之间求差进行判断
ReentrantLock实现机制的更多相关文章
- Java并发编程基础-ReentrantLock的机制
同步锁: 我们知道,锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源,在Lock接口出现之前,Java应用程序只能依靠synchronized关键字来实现同步锁 ...
- ReentrantLock原理学习
上文我们学习了ReentrantLock的基本用法,在最后我们留下了一个问题,ReentrantLock获取的锁是什么锁呢?本文我们就从源码的角度来一探究竟.本文涉及到的源码对应JDK版本为1.8. ...
- Synchronize和ReentrantLock区别
转自:https://blog.csdn.net/m0_37700275/article/details/83151850 目录介绍1.Synchronize和ReentrantLock区别 1.1 ...
- [转] 多线程 《深入浅出 Java Concurrency》目录
http://ifeve.com/java-concurrency-thread-directory/ synchronized使用的内置锁和ReentrantLock这种显式锁在java6以后性能没 ...
- 阿里,百度面试90%会问的Java面试题
题目一 请对比 Exception 和 Error,另外,运行时异常与一般异常有什么区别? 考点分析: 分析 Exception 和 Error 的区别,是从概念角度考察了 Java 处理机制.总的来 ...
- BATJ等公司必问的8道Java经典面试题,你都会了吗?
1.谈谈你对 Java 平台的理解?“Java 是解释执行”,这句话正确吗? 考点分析: 对于这类笼统的问题,你需要尽量表现出自己的思维深入并系统化,Java 知识理解得也比较全面,一定要避免让面试官 ...
- 《深入浅出 Java Concurrency》目录
最近在学习J.U.C,看到一个大神 关于这个系列写的非常精辟,由于想做笔记,故系列转载并记录之. 原文:http://www.blogjava.net/xylz/archive/2010/07/08/ ...
- Java之美[从菜鸟到高手演变]系列之博文阅读导航
随着博文越来越多,为博客添加一个导航很有必要!本博客将相继开通Java.CloudFoundry.Linux.Ruby等专栏,都会设立目录,希望读者朋友们能更加方便的阅读! 在阅读的过程中有任何问题, ...
- Java并发编程--3.Lock
Lock接口 它提供3个常用的锁 lock() : 获不到锁就就一直阻塞 trylock() :获不到锁就立刻放回 或者 定时的,轮询的获取锁 lockInterruptibly() : 获不到锁时阻 ...
- BAT等公司必问的8道Java经典面试题,你都会了吗?
工作多年以及在面试中,我经常能体会到,有些面试者确实是认真努力工作,但坦白说表现出的能力水平却不足以通过面试,通常是两方面原因: 1.“知其然不知其所以然”.做了多年技术,开发了很多业务应用,但似乎并 ...
随机推荐
- 读书笔记-C#8.0本质论-05
18.3 基于任务的异步编程模式 18.3.1 使用任务并行库(TPL)实现异步执行高延迟操作 using System; using System.Net.Http; using System.Th ...
- 深入JVM——栈和局部变量
java栈概述 记得当初我学习java时,常常听见身边的朋友说:"你要记住,当new一个对象时,对象的引用存放在栈里,而对象是存放在堆里的".当时,听到这句教导时,脑海里立即出现栈 ...
- Java反编译器剖析
本文由 ImportNew - 邬柏 翻译自 javacodegeeks.如需转载本文,请先参见文章末尾处的转载要求. Importnew注:如果你也对Java技术翻译分享感兴趣,欢迎加入我们的Jav ...
- AtCoder Beginner Contest 295
Three Days Ago 我们定义一个只由数字构成的字符串中的字符能够被重排成相同的两份,我们称这个字符串是个好字符串,比如12341234 现在给定一个字符串\(S\),找出所有的\([l,r] ...
- 交易系统:电商、O2O、线下门店购物流程详解
大家好,我是汤师爷~ 新零售业务涉及多个销售渠道,每个渠道都有其独特的业务特点,需要相应的营销方式.运营策略和供应链管理. 主要销售渠道包括:实体门店(包括直营连锁店.加盟门店).电商平台销售(如淘宝 ...
- HTML5 多媒体
1.互联网上的音频 直到现在,仍然不存在一项旨在网页上播放音频的标准. 今天,大多数音频是通过插件(比如 Flash)来播放的.然而,并非所有浏览器都拥有同样的插件. HTML5 规定了在网页上嵌入音 ...
- ORCA避障源码笔记
参考资料 https://gamma.cs.unc.edu/ORCA/publications/ORCA.pdf https://gamma.cs.unc.edu/RVO2/ 数学知识 1.向量的点乘 ...
- VLC web(http)控制 (1) 设置与登录
VLC3.0 web控制设置步骤: 1.打开偏好设置并显示全部: 2.进入主界面选项,选中Web: 3.进入Lua中设置HTTP密码: 重启软件生效. 这时就可以通过http://127. ...
- QT日志类SimpleQtLogger的简单记录
在现代软件开发中,日志记录是必不可少的部分.它不仅帮助开发者在调试和维护软件时了解程序的运行状态,还能提供关键的错误信息.对于使用Qt框架开发应用程序的开发者来说,选择一个合适的日志库至关重要.本文将 ...
- nginx的子路径重写替换
在nginx中配置proxy_pass代理转发时,如果在proxy_pass后面的url加/,表示绝对根路径:如果没有/,表示相对路径,把匹配的路径部分也给代理走. 假设下面四种情况分别用 http ...