首页 > 编程语言 >「java.util.concurrent并发包」之 AQS

「java.util.concurrent并发包」之 AQS

时间:2024-03-03 22:44:33浏览次数:27  
标签:int CLH AQS 队列 util concurrent state 线程 发包

AQS 的原理是什么?

AQS 核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制 AQS 是用 CLH 队列锁 实现的,即将暂时获取不到锁的线程加入到队列中。

CLH(Craig,Landin,and Hagersten) 队列是一个虚拟的双向队列(虚拟的双向队列即不存在队列实例,仅存在结点之间的关联关系)。AQS 是将每条请求共享资源的线程封装成一个 CLH 锁队列的一个结点(Node)来实现锁的分配。在 CLH 同步队列中,一个节点表示一个线程,它保存着线程的引用(thread)、 当前节点在队列中的状态(waitStatus)、前驱节点(prev)、后继节点(next)。

CLH 队列结构如下图所示:

AQS(AbstractQueuedSynchronizer)的核心原理图

AQS 使用 int 成员变量 state 表示同步状态,通过内置的 线程等待队列 来完成获取资源线程的排队工作。

state 变量由 volatile 修饰,用于展示当前临界资源的获锁情况。

// 共享变量,使用volatile修饰保证线程可见性
private volatile int state;

另外,状态信息 state 可以通过 protected 类型的getState()setState()compareAndSetState() 进行操作。并且,这几个方法都是 final 修饰的,在子类中无法被重写。

//返回同步状态的当前值
protected final int getState() {
     return state;
}
 // 设置同步状态的值
protected final void setState(int newState) {
     state = newState;
}
//原子地(CAS操作)将同步状态值设置为给定值update如果当前同步状态的值等于expect(期望值)
protected final boolean compareAndSetState(int expect, int update) {
      return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

ReentrantLock 为例,state 初始值为 0,表示未锁定状态。A 线程 lock() 时,会调用 tryAcquire() 独占该锁并将 state+1 。此后,其他线程再 tryAcquire() 时就会失败,直到 A 线程 unlock()state=0(即释放锁)为止,其它线程才有机会获取该锁。当然,释放锁之前,A 线程自己是可以重复获取此锁的(state 会累加),这就是可重入的概念。但要注意,获取多少次就要释放多少次,这样才能保证 state 是能回到零态的。

再以 CountDownLatch 以例,任务分为 N 个子线程去执行,state 也初始化为 N(注意 N 要与线程个数一致)。这 N 个子线程是并行执行的,每个子线程执行完后countDown() 一次,state 会 CAS(Compare and Swap) 减 1。等到所有子线程都执行完后(即 state=0 ),会 unpark() 主调用线程,然后主调用线程就会从 await() 函数返回,继续后余动作。

 

标签:int,CLH,AQS,队列,util,concurrent,state,线程,发包
From: https://www.cnblogs.com/balfish/p/18050906

相关文章

  • 「java.util.concurrent并发包」之 Unsafe
    一unsafe介绍Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别、不安全操作的方法,如直接访问系统内存资源、自主管理内存资源等,这些方法在提升Java运行效率、增强Java语言底层资源操作能力方面起到了很大的作用。但由于Unsafe类使Java语言拥有了类似C......
  • 为什么HashMap的键值可以为null,而ConcurrentHashMap不行?
    写在开头昨天在写《HashMap很美好,但线程不安全怎么办?ConcurrentHashMap告诉你答案!》这篇文章的时候,漏了一个知识点,直到晚上吃饭的时候才突然想到,关于ConcurrentHashMap在存储Key与Value的时候,是否可以存null的问题,按理说这是一个小问题,但build哥却不敢忽视,尤其在现在很多面试官都......
  • Go 100 mistakes - #92: Writing concurrent code that leads to false sharing
      ......
  • Lab1:Xv6 and Unix utilities
    Sleep功能通过接受时间参数,调用system_call指令sleep实现该功能#include"kernel/types.h"#include"kernel/stat.h"#include"user/user.h"intmain(intargc,char*argv[]){ //sleeptime if(argc<2) { printf("error:notime\n"......
  • HashMap很美好,但线程不安全怎么办?ConcurrentHashMap告诉你答案!
    写在开头在《耗时2天,写完HashMap》这篇文章中,我们提到关于HashMap线程不安全的问题,主要存在如下3点风险:风险1:put的时候导致元素丢失;如两个线程同时put,且key值相同的情况下,后一个线程put操作覆盖了前一个线程的操作,导致前一个线程的元素丢失。风险2:put和get并发时会导致g......
  • JUC系列之(四)ConcurrentHashMap锁分段机制
    ConcurrentHashMap锁分段机制1.关于HashMap和HashTableHashMap:线程不安全HashTable:效率低:操作时锁整个表复合操作会带来安全问题//table.contains()和table.put()分别都是加了锁的,但是像下述复合操作,一个线程判断完之后CPU可能被其他线程抢夺,带来安全问题if(!table.c......
  • Qt Cannot open include file: 'QtConcurrent': No such file or directory
    假期手痒用Qt写了个便笺程序,其中文件操作用到了QtConcurrent模块。噼里啪啦,一通猛如虎的操作下来,代码写完了,愉快地build+run一套,结果报错了:(Cannotopenincludefile:'QtConcurrent':Nosuchfileordirectory编译不过一声吼,操起鼠标查google。官方文档就是这么写的看......
  • from Crypto.Util.Padding import pad,unpad 报错,没有找到依赖
    1、安装pipinstallpycryptodomepipinstallCrypto2、安装完成后重启idea,发现还是没有打开依赖包所在的文件夹:安装位置\Lib\site-packages发现Crypto是小写,将代码中的引入改成小写fromcrypto.Util.Paddingimportpad,unpad 3、打开crypto文件夹,看到Util和Ciph......
  • ConcurrentHashMap 核心源码解析
    废话不多说,直接看代码类名与HashMap很相似,数组、链表结构几乎相同,都实现了Map接口,继承了AbstractMap抽象类,大多数的方法也都是相同的publicclassConcurrentHashMap<K,V>extendsAbstractMap<K,V>implementsConcurrentMap<K,V>,Serializable核心方法Node方法......
  • 「java.util.concurrent并发包」之 Semaphore
    一Semaphore是什么Semaphore也叫信号量,在JDK1.5被引入,可以用来控制同时访问特定资源的线程数量,通过协调各个线程,以保证合理的使用资源。Semaphore内部维护了一组虚拟的许可,许可的数量可以通过构造函数的参数指定。访问特定资源前,必须使用acquire方法获得许可,如果许可数量为0......