aqs clh java_【Java并发编程实战】----- AQS(一):简介

在前面博客中,LZ讲到了ReentrantLock、ReentrantReadWriteLock、Semaphore、CountDownLatch,他们都有各自获取锁的方法,同时相对于Java的内置锁,他们具有明显的优势:花最小的空间开销创建锁、最少的时间开销获得锁、使用更加方便灵活。

参考Java的内置锁,对于JUC同步器而言,他应该具备两个最基本的功能:获取锁,释放锁。其中获取锁应该是先判断当前状态是否可以获取,如果不可以获取则处于阻塞状态,释放应该是释放后修改状态,让其他线程能够得到该锁(唤醒其他线程),如下:

lock:while(state){ // getLock(); //获取锁

return currentThread; //返回当前线程

}

release:

updateState();//修改状态

notify other thread; //唤醒其他线程

我们知道,在JUC中,各个同步器获取锁和释放锁的方法都不相同,比如:lock.lock()、Semaphore.acquire()、 CountDownLatch.await()等等,假如他们都各自实现各自的方法,那么这个JUC框架顶多只能算一个中下等的框架设计了。这是AQS腾空出世,AQS作为一个核心的处理框架,他提供了大量的同步操作,同时用户还可以在此类的基础上进行自定义,实现自己的同步器。其主要框架如下:

eab6fed0a771789cd20d2e49bfd09a18.png

从上图可以看出AQS是JUC同步器的基石。下面就AQS涉及的技术原理简单阐述下,以后会对其做详细的说明。

1、状态位state

AQS用的是一个32位的整型来表示同步状态的,它是用volatile修饰的:

private volatile int state;

在互斥锁中它表示着线程是否已经获取了锁,0未获取,1已经获取了,大于1表示重入数。同时AQS提供了getState()、setState()、compareAndSetState()方法来获取和修改该值:

protected final intgetState() {returnstate;

}protected final void setState(intnewState) {

state=newState;

}protected final boolean compareAndSetState(int expect, intupdate) {return unsafe.compareAndSwapInt(this, stateOffset, expect, update);

}

这些方法需要java.util.concurrent.atomic包的支持,采用CAS操作,保证其原则性和可见性。

2、CLH同步队列

在前面就提到过AQS内部维护着一个FIFO的CLH队列,所以AQS并不支持基于优先级的同步策略。至于为何要选择CLH队列,主要在于CLH锁相对于MSC锁,他更加容易处理cancel和timeout,同时他具备进出队列快、无所、畅通无阻、检查是否有线程在等待也非常容易(head != tail,头尾指针不同)。当然相对于原始的CLH队列锁,ASQ采用的是一种变种的CLH队列锁:

1、原始CLH使用的locked自旋,而AQS的CLH则是在每个node里面使用一个状态字段来控制阻塞,而不是自旋。

2、为了可以处理timeout和cancel操作,每个node维护一个指向前驱的指针。如果一个node的前驱被cancel,这个node可以前向移动使用前驱的状态字段。

3、head结点使用的是傀儡结点。

b7c465948645e4f949d2e0b8efc55e4c.png

3、共享锁、互斥锁

在AQS维护的CLH队列锁中,每个节点(Node)代表着一个需要获取锁的线程。该Node中有两个常量SHARE、EXCLUSIVE。其中SHARE代表着共享模式,EXCLUSIVE代表着独占模式。

static final classNode {/**Marker to indicate a node is waiting in shared mode*/

static final Node SHARED = newNode();/**Marker to indicate a node is waiting in exclusive mode*/

static final Node EXCLUSIVE = null;/

}

其中共享模式是允许多个线程可以获取同一个锁,而独占模式则一个锁只能被一个线程持有,其他线程必须要等待。

4、阻塞、唤醒

我们知道在使用Java内置锁时,可以使用wait、notify方法来阻塞、唤醒线程,但是AQS并没有采用该模式,而是通过LockSupport.park() 和 LockSupport.unpark() 的本地方法来实现线程的阻塞和唤醒。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/558068.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gitlab ci 配置 java_GitLab CI/CD 配置

GitLab CI/CD 配置概念操作示例创建测试项目 sample-web,然后打开项目的 Runners 配置找到这个地方,后边要用然后搭建 gitlab-runner,CI/CD 需要通过它实现# 创建 gitlab-runner 目录mkdir -p /usr/local/gitlab-runner && cd /usr/l…

java失败javac成功_JAVA SE JDK-10安装、配置(解决java成功,javac失败问题)

本文是在win10环境下安装JDK-10在linux环境下安装JDK-10请点击:CentOS 7 安装、配置JDK-101、下载JDK包点击打开下载网站点击图中的Accept License Agreement,再选择Win版本进行下载2、安装JDK包下载完毕,运行安装程序修改安装路径(这里选择的…

java搭建聊天服务器_使用 ServerSocket 建立聊天服务器-2

1.从serverListener中可以看出,每一个客户端创建新的请求之后,都会把它分配给一个独立的chatsocket ,但是每一个ChatSocket都是相互独立的,他们之间并不能沟通,所以要新建一个类,将这些新建的线程管理起来,然后实现他们之间的相互通信.(类似于微信加群聊天的功能)由于一个聊天服…

lavarel php区别,laravel中{{}}和{!! !!}的区别详解

本篇文章介绍了laravel中{{}}和{!! !!}的区别,感兴趣的朋友可以参考下。laravel中{{}}和{!! !!}的区别详解1.{{}}和{!! !!} 中{{}}支持转义 一段html代码只是被当成普通的字符串输出 ,{!! !!} 不支持转义 一段html代码可以被正常的解析1.2具体什么意思呢…

php获取ios,IOS 通过描述获取UDID PHP代码版

难点在于PHP对XML的解析文件结构:第一步:新建HTML文件 用于跳转安装描述文件 必须在safari里面打开地址第二步:新建udid.mobileconfig文件PayloadContentURLhttps://www.xxx.com/pay_super/receive.phpDeviceAttributesUDIDIMEIICCIDVERSIONP…

matlab如何读取csv,Matlab:如何读取CSV文件以及如何读取带有字符串数据项的CSV文件 | 学步园...

CSV,逗号分开的文件,如果能快速的读取这些文件中的数据,无疑会帮助我们解决很多问题。1、 只有数据的CSV文件,CSV file that includes only numbers.As an example, create a text file, named as data.csv if you prefer, which …

url中隐藏php后缀,url中如何隐藏.php

url中隐藏“.php”的方法:首先找到并打开“nginx.conf”配置文件;然后添加内容“location / {ttry_files $uri $uri/ $uri.php$is_args$args;}”;最后保存修改即可。推荐:《PHP视频教程》现在很多人都喜欢用nginx作为Web服务器部署…

discuz手机客户端java,Discuz!7.2让高级搜索更全面

Discuz! 7.2 调整了对帖子的高级搜索,使高级搜索的搜索选项更细化,覆盖面更广。一、高级搜索功能介绍高级搜索界面如下图所示:1、按作者:此处可以填写发帖作者全名,也可以使用通配符"*",如填写&q…

php面向对象异常处理,PHP 错误和异常处理(下)

PHP 错误和异常处理(下)由 学院君 创建于9个月前, 最后更新于 7个月前版本号 #11723 views2 likes0 collects上篇我们讲了 PHP 中的错误报告和捕获,今天,我们来看看 PHP 程序中的异常处理。错误 vs. 异常错误与异常可以看作一对孪生兄弟,从严…

电脑运行java游戏,电脑运行软件卡顿?这几招游戏或是办公,让你速度飞起!...

许多朋友想知道他们已经购买了高端计算机,但是无论玩游戏还是运行软件,他们仍然陷于困境。今天,让我们教大家一个简单的方法来提高计算机性能。焦点:此方法大大提高了用户对高度配置的计算机的影响。如果计算机的设置不太高&#…

c matlab 数据类型,matlab中数据类型与c语言数据类型的区别?

matlab中数据类型与c语言数据类型的区别?mip版 关注:233 答案:3 悬赏:0解决时间 2021-02-23 08:46已解决2021-02-22 22:32matlab中数据类型与c语言数据类型的区别?最佳答案2021-02-22 22:42简单谈一下。1.好多类型是对应的。输入一个数,ma…

oracle数据库安装提示M,Python第13课:oracle数据库的安装

Python第13课:oracle数据库的安装时间 2019-01-22下午4:30主讲 罗恒丰地点 四楼电教室版本:11.2大小:2.06G安装文件在专班ftp里python安装文件的文件夹。一.找到 stage/cvu/cvu_prereq.xml ,编辑系统名,以适…

linux 文件怎么不让删,请问如何设置权限,可以禁止用户删除文件

原帖由 WHITLACK 于 2009-9-28 08:48 发表 针对某个文件,如何设置权限,可以禁止删除?文件权限的r-w-x好像不能禁止删除的啊,谢谢指教!1:使用粘滞位可以做到,下面是介绍.强制位与冒险位、粘滞位针对u,g&…

linux运行中望cad,国产CAD软件中望的Linux版适配UOS, 我在国产系统里试了试

可能大家都知道,以往我们在国产操作里运行的软件,很多都是国外开源的软件。在以前很长一段时间里,国产操作中,国内企业很少去适配的。据说,国产深度之所以有很多国产软件,其中一个原因就是他们一家一家去拜…

linux内核死锁检测机制 | oenhan,Linux内核CPU负载均衡机制 | OenHan

还是神奇的进程调度问题引发的,参看Linux进程组调度机制分析,组调度机制是看清楚了,发现在重启过程中,很多内核调用栈阻塞在了double_rq_lock函数上,而double_rq_lock则是load_balance触发的,怀疑当时的核间…

linux下IPROTO_TCP,TCP/IP协议栈在Linux内核中的运行时序分析

可选题目三:TCP/IP协议栈在Linux内核中的运行时序分析在深入理解Linux内核任务调度(中断处理、softirg、tasklet、wq、内核线程等)机制的基础上,分析梳理send和recv过程中TCP/IP协议栈相关的运行任务实体及相互协作的时序分析。编译、部署、运行、测评、…

vs2019Linux守护,Visual Studio 2019将支援Ninja显着提升Linux专案建置效率

微软更新Visual Studio 2019,新增多个可提升Linux开发体验的功能,包括在Linux上支援建置系统Ninja,以及更完整地支援gdbserver,而且现在开发者也可以使用连接管理器(Connection Manager),编辑和配置预设的远端连接。使…

c语言程序中必不可少的,C语言程序设计(第3章程序控制语句)2

3.2 数据的输入与输出在程序的运行过程中,往往需要由用户输入一些数据,而程序运算所得到的计算结果等又需要输出给用户,由此实现人与计算机之间的交互,所以在程序设计中,输入输出语句是一类必不可少的重要语句&#xf…

android 九宫格封装,Android 九宫格布局

演示image需求满足0-9个图的适配图数量演示1image2image3image4image5image6image7image8image9image使用手动设置android:layout_width"match_parent"android:layout_height"wrap_content"app:ngl_gridSpace"10dp"app:ngl_oneChildHeight"…

android放大镜无广告,Android放大镜的实现代码

快三个月了没写博客了,因为工作调动,很多经验、心得都没有时间记录下来。现在时间稍微充裕了点,我会尽量抽时间将之前想写而没写的东西补上。进入正题。去年某个时候,我偶然看到一篇文章,讲android里面放大镜的实现。文…