导航:首页 > 源码编译 > 同步器aqs框架源码

同步器aqs框架源码

发布时间:2023-01-01 09:27:06

㈠ AQS源码解析(6)acquireInterruptibly

reentrantlock中有lockInterruptibly函数,表示可响应中断,之前讲的lock是不会响应中断的:

lockInterruptibly核心函数:

doAcquireInterruptibly:

㈡ 多线程-AQS总结

一个排他锁ReentrantLock,一个ReenTrantReadWriteLock,3个同步器分别是CountDownLatch、Semaphore、CyclicBarrier(内部直接使用ReentrantLock,其他都有一个内部类Sync extends AQS)

如上图Node节点,下面解析一下属性

其中waitStatus是个枚举

源码阅读见另外一篇博客

例如现在有3个线程A、B、C按顺序获取锁,并且A线程一直占用锁

源码阅读见另外一篇博客

例如现在有6个线程A(读)、B(读)、C(写)、D(读)、E(读)、F(写)按顺序获取锁

源码阅读见另外一篇博客

例如,主线程A创建CountDownLatch(2),创建2条线程的线程池,线程B、C

例如,主线程A创建CyclicBarrier(2,屏障点方法),创建2条线程的线程池,线程B、C

例如,线程A创建Semaphore(2),创建3条线程的线程池,线程B、C、D

参考地址: https://blog.csdn.net/wangnanwlw/article/details/109509685?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-1.not_use_machine_learn_pai&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-1.not_use_machine_learn_pai

㈢ AQS研究系列(一)--Unsafe使用

为了研究AQS,我们先来学习下java中cas(Compare And Swap)的基础Unsafe类的使用

Unsafe产生于java无法向c那样操作底层操作系统,但一些场景又需要相关操作.所以此类提供了一些java语言对于操作系统内存层面操作的API.这显然被认为是不安全的,所以此类是不公开的,不建议被java应用直接使用.
但现实中已经有大量的java并发相关操作的框架在使用它了....据说此类在计划废弃中.

Unsafe能操作内存?这个是什么概念?都有哪些操作呢?

其实最明显的是它大量方法都是直接操作内存地址进行操作的.方法可以分为下面几类:

我们可以使用LockSupport类进行操作

a. LockSupport.park()对应Unsafe的Unsafe.park(false, 0L)------>给当前所在线程加锁,第一个参数表示true为精度型单位为纳秒,false单位毫秒,第二次参数表示等待时间;

b. LockSupport.park.unpark --------->Thread thread对应Unsafe的UNSAFE.unpark(thread)方法(解锁指定线程)
如果,我们直接使用Unsafe,是这样子的:

我们还可以通过Unsafe类获取对象的属性值.因为Unsafe类是直接操作内存的,所以需要我们获得对应的属性内存地址,如下操作:

如下操作,通过unsafe类实现cas原子操作.

好了,上面就是unsafe的基本几种使用,其也是aqs框架中cas操作的基础.下面我们进行aqs相关学习.

AQS研究系列(二)--线程状态和interrupt()、interrupted()、isInterrupted等方法学习
AQS研究系列(三)--AbstractQueuedSynchronizer源码分析

㈣ aqs原理是什么

aqs原理:

是一个用于构建锁和同步器的框架,它能降低构建锁和同步器的工作量,还可以避免处理多个位置上发生的竞争问题,在基于AQS构建的同步器中,只可能在一个时刻发生阻塞,从而降低上下文切换的开销,并提高吞吐量。

相关信息:

AQS内部实现了两个队列,一个同步队列,一个条件队列。

同步队列的作用是:当线程获取资源失败之后,就进入同步队列的尾部保持自旋等待,不断判断自己是否是链表的头节点,如果是头节点,就不断参试获取资源,获取成功后则退出同步队列。

条件队列是为Lock实现的一个基础同步器,并且一个线程可能会有多个条件队列,只有在使用了Condition才会存在条件队列。

㈤ J.U.C|同步队列(CLH)

在上篇我们聊到AQS的原理,具体参见 《J.U.C|带你走进AQS的内心世界》 。

这篇我们来给大家聊聊AQS中核心同步队列(CLH)。

同步队列

一个FIFO双向队列,队列中每个节点等待前驱节点释放共享状态(锁)被唤醒就可以了。

AQS如何使用它?

AQS依赖它来完成同步状态的管理,当前线程如果获取同步状态失败时,AQS则会将当前线程已经等待状态等信息构造成一个节点(Node)并将其加入到CLH同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点唤醒(公平锁),使其再次尝试获取同步状态。

Node节点面貌?

CLH同步队列的结构图

这里是基于CAS(保证线程的安全)来设置尾节点的。

如上图了解了同步队列的结构, 我们在分析其入列操作在简单不过。无非就是将tail(使用CAS保证原子操作)指向新节点,新节点的prev指向队列中最后一节点(旧的tail节点),原队列中最后一节点的next节点指向新节点以此来建立联系,来张图帮助大家理解。

源码
源码我们可以通过AQS中的以下两个方法来了解下
addWaiter方法

先通过addWaiter(Node node)方法尝试快速将该节点设置尾成尾节点,设置失败走enq(final Node node)方法

enq

通过“自旋”也就是死循环的方式来保证该节点能顺利的加入到队列尾部,只有加入成功才会退出循环,否则会一直循序直到成功。

上述两个方法都是通过compareAndSetHead(new Node())方法来设置尾节点,以保证节点的添加的原子性(保证节点的添加的线程安全。)

同步队列(CLH)遵循FIFO,首节点是获取同步状态的节点,首节点的线程释放同步状态后,将会唤醒它的后继节点(next),而后继节点将会在获取同步状态成功时将自己设置为首节点,这个过程非常简单。如下图

设置首节点是通过获取同步状态成功的线程来完成的(获取同步状态是通过CAS来完成),只能有一个线程能够获取到同步状态,因此设置头节点的操作并不需要CAS来保证,只需要将首节点设置为其原首节点的后继节点并断开原首节点的next(等待GC回收)应用即可。

聊完后我们来总一下,同步队列就是一个FIFO双向对队列,其每个节点包含获取同步状态失败的线程应用、等待状态、前驱节点、后继节点、节点的属性类型以及名称描述。

其入列操作也就是利用CAS(保证线程安全)来设置尾节点,出列就很简单了直接将head指向新头节点并断开老头节点联系就可以了。

阅读全文

与同步器aqs框架源码相关的资料

热点内容
溯源码有分国家认证的吗 浏览:210
如何通过app查询产检报告 浏览:938
拉结尔安卓手机怎么用 浏览:695
驱动级进程代理源码 浏览:782
androidshape画线 浏览:510
程序员想辞职被拒绝 浏览:101
java面试逻辑 浏览:749
如何下载全英文app 浏览:724
js函数式编程指南 浏览:380
为什么安卓手机相机启动会卡 浏览:341
python中t是什么意思 浏览:765
移动硬盘内存加密 浏览:407
单片机测角度 浏览:864
URL服务器地址怎么填 浏览:438
压缩饼干会导致血糖高吗 浏览:569
cad中xc命令怎么用 浏览:424
戴尔服务器怎么看网卡接口 浏览:823
盐铁论pdf 浏览:424
最短路径的生成算法可用 浏览:457
苹果备忘录怎么不能加密了 浏览:626