面试准备-Java并发/AQS

本文详细介绍了Java并发库中的核心组件AbstractQueuedSynchronizer(AQS),包括其原理、数据结构、线程如何加入和出队等待队列,以及独占式和共享式同步状态的获取和释放。AQS作为Java锁和其他同步组件的基础,如ReentrantLock,通过维护同步状态和FIFO等待队列来实现线程的同步。文章还探讨了公平锁和非公平锁的实现差异。
摘要由CSDN通过智能技术生成

目录

简介

原理

1. AQS数据结构

2. 同步状态State

3. 线程加入等待队列

加入队列的时机

如何加入队列

4. 等待队列中线程出队列时机

代码设计

独占式同步状态获取

独占式同步状态释放

共享式同步状态获取

共享式同步状态释放

其它问题

ReentrantLock

非公平锁

公平锁


简介

Java中的大部分同步类(Lock、Semaphore、ReentrantLock等)都是基于AbstractQueuedSynchronizer(简称为AQS)实现的。AQS是一种提供了原子式管理同步状态、阻塞和唤醒线程功能以及队列模型的简单框架。

在AQS中的锁类型有两种:分别是Exclusive(独占锁)和Share(共享锁)。

「独占锁」就是「每次都只有一个线程运行」,例如ReentrantLock

「共享锁」就是「同时可以多个线程运行」,如Semaphore、CountDownLatch、ReentrantReadWriteLock

原理

AQS核心思想是,如果被请求的共享资源空闲,那么就将当前请求资源的线程设置为有效的工作线程,将共享资源设置为锁定状态;如果共享资源被占用,则调用LockSupport().park()方法将Node中的线程状态改为WAITING,等待被唤醒或被中断 ,就需要一定的阻塞等待唤醒机制来保证锁分配。这个机制主要用的是CLH队列的变体实现的,将暂时获取不到锁的线程加入到队列中。

CLH:Craig、Landin and Hagersten队列,是单向链表,AQS中的队列是CLH变体的虚拟双向队列(FIFO),AQS是通过将每条请求共享资源的线程封装成一个节点来实现锁的分配。

主要原理图如下:

AQS使用一个Volatile的int类型的成员变量来表示同步状态,通过内置的FIFO队列来完成资源获取的排队工作,通过CAS完成对State值的修改。

在FIFO队列中,头节点占有锁,也就是头节点才是锁的持有者,尾指针指向队列的最后一个等待线程节点,除了头节点和尾节点,节点之间都有前驱指针后继指针

在AQS中维护了一个共享变量state,标识当前的资源是否被线程持有,多线程竞争的时候,会去判断state是否为0,尝试的去把state修改为1。

1. AQS数据结构

AQS中最基本的数据结构——Node,Node即为上面CLH变体队列中的节点。

解释一下几个方法和属性值的含义:

方法和属性值 含义
waitStatus 当前节点在队列中的状态
thread 表示处于该节点的线程
prev 前驱指针
predecessor 返回前驱节点,没有的话抛出npe
nextWaiter 指向下一个处于CONDITION状态的节点
next 后继指针

线程两种锁的模式:

模式 含义
SHARED(shared) 表示线程以共享的模式等待锁
EXCLUSIVE(exclusive) 表示线程正在以独占的方式等待锁

waitStatus有下面几个枚举值:

枚举 含义
0 当一个Node被初始化的时候的默认值
CANCELLED(cancelled) 为1,表示线程获取锁的请求已经取消了
CONDITION(condition) 为-2,表示节点在等待队列中,节点线程等待唤醒
PROPAGATE(propagate) 为-3,当前线程处在SHARED情况下,该字段才会使用
SIGNAL(signal) 为-1,表示线程已经准备好了,就等资源释放了

2. 同步状态State

AQS中维护了一个名为state的字段,意为同步状态,是由Volatile修饰的,用于展示当前临界资源的获锁情况。

// java.util.concurrent.locks.AbstractQueuedSynchronizer
private volatile int state;

访问这个字段的方法:

方法名 描述
protected final int getState() 获取State的值
protected final void setState(int newState) 设置State的值
protected final boolean compareAndSetState(int expect, int update) 使用CAS方式更新State

这几个方法都是Final修饰的,说明子类中无法重写它们。我们可以通过修改State字段表示的同步状态来实现多线程的独占模式和共享模式(加锁过程)。

【独占模式】

【共享模式 】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值