导航:首页 > 源码编译 > 同步器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框架源码相关的资料

热点内容
表盘编程gt 浏览:7
java源代码阅读 浏览:734
程序员用什么键盘罗技 浏览:167
为什么安卓手机每天都要更新app 浏览:705
java怎么成为程序员 浏览:288
西门子s7200编程电缆怎么连接 浏览:530
下载网页中的pdf文件 浏览:87
音乐缓存文件夹的软件 浏览:394
Dkms编译打印机驱动 浏览:992
解压缩文件操作异常 浏览:556
等待代码编译时你会干嘛 浏览:493
单片机c语言中变量右移8位 浏览:81
解压的一个小短片 浏览:831
二级压缩空压机哪家好排行 浏览:743
基于单片机超声波测距 浏览:130
模拟随机红包算法 浏览:386
程序员接外包网站 浏览:135
哪里可以买拆车件app 浏览:992
限流算法漏桶和令牌桶区别 浏览:316
程序员怎么找兼职 浏览:802