ReentrantLock的底层实现机制 AQS
ReentrantLock的底层实现机制是AQS(Abstract Queued Synchronizer 抽象队列同步器)。AQS没有锁之类的概念,它有个state变量,是个int类型,为了好理解,可以把state当成锁,AQS围绕state提供两种基本操作“获取”和“释放”,有条双向队列存放阻塞的等待线程。AQS的功能可以分为独占和共享,ReentrantLock实现了独占功能(每次只能有一个线程能持有锁)。
在ReentrantLock类中,有一个内部类Sync,它继承了AQS,但是将lock()方法定义为抽象方法,由子类负责实现(采用的是模板方法的设计模式)。
abstract void lock();
Sync分为公平锁和非公平锁,所以又有FairSync和NonfairSync继承Sync。
ReentrantLock的默认构造实现是非公平锁,也就是线程获取锁的顺序和调用lock的顺序无关。所有线程同时去竞争锁,线程发出请求后立即尝试获取锁,如果有可用的则直接获取锁,失败才进入等待队列。

在非公平锁NonfairSync中,

线程只要有机会就抢占,才不管排队的事。直接尝试将state修改为1,如果修改state失败,则和公平锁一样,调用acquire。(乐观锁的思想)
在公平锁FairSync中,线程去竞争一个锁,可能成功也可能失败。成功就直接持有资源,不需要进入队列;失败的话进入队列阻塞,等待唤醒后再尝试竞争锁。

首先尝试着去获取锁,如果state的当前状态为0,且没有前继线程在等待,表明没有线程占用,此时可以获得锁,然后设置当前线程为独占线程,并返回true,此时不会调用acquireQueued()方法(&& : 只有当&&左边程序为真,才会执行&&右边的程序,否者不会执行后面的),且不会执行selfInterrupt()方法。

相反,如果获取锁失败,则会执行
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)
该首先会将当前线程包装成一个Node,插入到双向队列尾

标记1判断该Node的前继节点p,如果前一个节点正好是head,表示自己排在第一位,可以马上调用tryAcquire尝试。如果获取成功就简单了,直接修改自己为head。这步是实现公平锁的核心。标记2是线程没有获取到锁的情况(当前线程没有排到第一位),这个时候,线程可能等着下一次获取,也可能不想要了,Node变量waitState描述了线程的等待状态。

shouldParkAfterFailedAcquire()方法会根据前一个节点的waitStatus作出抉择,如果前节点状态是SIGNAL,则当前线程需要阻塞。

如果线程需要阻塞,则由parkAndCheckInterrupt()方法进行操作。LockSupport和cas一样,最终使用UNSAFE调用Native方法实现线程阻塞(park和unpark方法作用类似于wait和notify)

释放锁:
public void unlock() {
sync.release(1);
}
头节点是获取锁的线程,如果tryRelease()释放成功,会将头节点先移出队列,再通知后面的节点获取锁

如果有后继节点,则唤醒线程,重新尝试去获取锁。

ReentrantLock的底层实现机制 AQS的更多相关文章
- ReentrantLock 源码分析以及 AQS (一)
前言 JDK1.5 之后发布了JUC(java.util.concurrent),用于解决多线程并发问题.AQS 是一个特别重要的同步框架,很多同步类都借助于 AQS 实现了对线程同步状态的管理. A ...
- <转>ASP.NET学习笔记之理解MVC底层运行机制
ASP.NET MVC架构与实战系列之一:理解MVC底层运行机制 今天,我将开启一个崭新的话题:ASP.NET MVC框架的探讨.首先,我们回顾一下ASP.NET Web Form技术与ASP.NET ...
- 【Spark 深入学习 04】再说Spark底层运行机制
本节内容 · spark底层执行机制 · 细说RDD构建过程 · Job Stage的划分算法 · Task最佳计算位置算法 一.spark底层执行机制 对于Spark底层的运行原理,找到了一副很好的 ...
- .net core系列之《从源码对Configuration的底层运行机制进行分析》
通过对Configuration源代码的分析从而来自定义一个配置数据源 1.用反编译工具来看看AddJsonFile()这个方法究竟干了什么,源代码如下: public static IConfigu ...
- Spring AOP简介与底层实现机制——动态代理
AOP简介 AOP (Aspect Oriented Programing) 称为:面向切面编程,它是一种编程思想.AOP 是 OOP(面向对象编程 Object Oriented Programmi ...
- Spring的底层实现机制
Spring的底层实现机制是通过Demo4j+java反射机制实现的. 使用demo4j来解析xml,使用反射机制实例化bean.
- AQS:Java 中悲观锁的底层实现机制
介绍 AQS AQS(AbstractQueuedSynchronizer)是 Java 并发包中,实现各种同步组件的基础.比如 各种锁:ReentrantLock.ReadWriteLock.Sta ...
- 深入浅出 Java Concurrency 锁机制 : AQS
转载:http://www.blogjava.net/xylz/archive/2010/07/06/325390.html 在理解J.U.C原理以及锁机制之前,我们来介绍J.U.C框架最核心也是最复 ...
- ReentrantLock的实现原理及AQS和CAS
AQS,即AbstractQueuedSynchronizer, 队列同步器,它是多线程访问共享资源的同步器框架,Java中的ReentrantLock/Semaphore/CountDownLatc ...
随机推荐
- WinFrom 第三方控件 TeleRik控件
1.首先从工具-拓展与应用中下载安装 TeleRik WinFroms VsExtensions TeleRik dll文件 2.工具箱控件 将Telerik控件更新过来 3.新建一个 ...
- THINKPHP5加载公共头部尾部模板方法
之前在3.2中用 <include file="public/header" /> 后来发现在thinkphp5中应该这样写才行 {include file=" ...
- ArcGIS -- ArcSDE Lock request conflicts with an established lock
1.查询下列表是否有数据 select * from sde.state_locks; select * from sde.object_locks; select * from sde.layer_ ...
- shell脚本学习总结06--数学计算
在bash中可利用let,(())和[]执行基本的操作,高级操作将会使用expr和bc 运算符:+,—,*,/,**(幂) (()) [root@Director ~]# ((c=2**3-9%2)) ...
- JavaScript作用域原理——作用域根据函数划分
一.一个for实例 <p id="scope3" style="color:red"></p> var pscope3 = docume ...
- 延迟加载JavaScript
上代码: 这段代码放到HTML文档的</body>标签之前(靠近HTML文档底部).外部脚本的名称为defer.js. <script type="text/javascr ...
- 部分常用dos命令
Microsoft Windows XP [版本 ] (C) 版权所有 - Microsoft Corp. C:\Documents and Settings\Administrator>d: ...
- docker-compose 部署 selenium-grid
目录 一.安装Docker 二.安装Docker-Compose库 三.准备docker-compose.yaml文件 四.运行 上篇:详细介绍selenium-grid 一.安装Docker 必须要 ...
- java开源模板引擎
Velocity Velocity是一个基于java的模板引擎(template engine).它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义 ...
- Windows的445端口(文件共享)
周鸿祎:教育网大量电脑445端口暴露,导致中招_科技_腾讯网 http://tech.qq.com/a/20170513/016133.htm 互联网周鸿祎2017-05-13 12:04 据36 ...