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 ...
随机推荐
- python3----练习题(图片转字符画)
import argparse from PIL import Image def parse_param(): parser = argparse.ArgumentParser() # 命令行输入参 ...
- ios 开发之 -- UILabel的text竖行显示
让UILabel的内容竖行显示,我经常用一下两种方式: 第一种:使用换行符 \n label.text = @"请\n竖\n直\n方\n向\n排\n列"; label.number ...
- PHP获取当前日期和时间格式化方法
使用函式 date() 实现 <?php echo $showtime=date("Y-m-d H:i:s");?> 显示的格式: 年-月-日 小时:分钟:妙 相关时间 ...
- ERROR in [copy-webpack-plugin] unable to locate "D:/xxx/xxx/xxx"
vue打包的时候npm run build报错 ERROR in [copy-webpack-plugin] unable to locate "D:/xxx/xxx/xxx" 这 ...
- 第一个MapReduce的例子
第一个MapReduce的例子 Hadoop Guide的第一个MapReduce的例子是处理气象数据的(数据来源ncdc),终于跑通了.总结一下步骤,安装hadoop不在本文中介绍 1 数据预处理 ...
- Linux Tar 命令简明教程
Tar 命令经常用但是它的各种参数又总是记不住,因此彻底梳理了一下,再也不会忘记. Tar 是 Linux 中的(压缩)归档工具. 归档的意思与打包相同,就是把文件或目录或者多个文件和目录打包为一个文 ...
- Hadoop单点伪分布模式安装
Hadoop单点伪分布模式安装 概述 单点 single-node,单节点,即一台计算机. 伪分布式模式 pseudo-distributed mode 所谓集群,表面上看是多台计算机联合完成任务:但 ...
- css如何引入外部字体?
第一步,在CSS中引入字体并给名字取一个合适的名字,如下 1 2 3 4 5 6 7 @font-face { /* font-properties */ font-family: p ...
- mysql数据库默认编码配置
修改my.ini文件 以下添加[mysql] default-character-set=utf8[mysqld] character_set_server = utf8init_connect='S ...
- CGI/FastCGI/mod_php工作原理
先了解一下普通cgi的工作流程:web server收到用户请求,并把请求提交给cgi程序,cgi程序根据请求提交的参数作相应处理,然后输出标准的html语句返回给web server,web ser ...