[Java并发]AQS的可重入性

news/2024/10/3 23:13:30

在Java中,AQS(AbstractQueuedSynchronizer,抽象队列同步器)通过设计一个独占和共享的同步机制,提供了可重入锁的实现。AQS 的可重入性主要依赖于它对线程状态的跟踪。具体来说,可重入性是指同一个线程在获得锁之后可以多次进入(加锁多次),而不引发死锁。这是通过一个“重入计数器”来实现的。

下面是AQS实现可重入性的核心机制:

1. 线程持有状态(state)

AQS 使用一个 state 变量来表示锁的持有状态。在独占锁(如 ReentrantLock)的情况下,state 变量记录锁被持有的次数。AQS 的设计允许同一个线程多次获取锁,每次获取锁时,state 变量会递增,而每次释放锁时,state 变量会递减,直到 state 变为 0 时,锁才会真正释放。

2. 当前持有锁的线程

AQS 通过内部的一个线程引用 exclusiveOwnerThread 来跟踪当前持有锁的线程。当一个线程尝试获取锁时,AQS 会检查当前线程是否已经持有锁(即 exclusiveOwnerThread == currentThread)。如果是同一个线程,则允许该线程再次获取锁,表示“可重入”。

3. 可重入的判断过程

  • 当一个线程第一次获取锁时,AQS 会将 exclusiveOwnerThread 设置为该线程,并将 state 从 0 设置为 1。
  • 如果同一线程再次尝试获取锁,AQS 看到 exclusiveOwnerThread 已经是当前线程,于是允许锁的重入,并将 state 递增。
  • 当线程释放锁时,AQS 会减少 state 的值。只有当 state 减为 0 时,AQS 才会将 exclusiveOwnerThread 置为 null,表示锁已完全释放。

4. 代码示例

ReentrantLock 为例,ReentrantLock 是基于 AQS 实现的可重入锁:

class ReentrantLockExample {private final ReentrantLock lock = new ReentrantLock();public void performTask() {lock.lock(); // 第一次加锁try {// 执行任务anotherMethod(); // 同一线程可以再次加锁} finally {lock.unlock(); // 第一次解锁}}public void anotherMethod() {lock.lock(); // 第二次加锁try {// 执行其他任务} finally {lock.unlock(); // 第二次解锁}}
}

在这个例子中,performTaskanotherMethod 都会加锁,而由于是同一线程,所以 lock 会被允许多次加锁。

5. 锁的释放

当线程多次加锁时,每次加锁都对应一次释放。只有当释放次数与加锁次数相等时,锁才会真正释放,允许其他线程获取。

总结

AQS 的可重入性主要是通过 state 变量和 exclusiveOwnerThread 来实现的。它通过跟踪线程加锁的次数以及锁的当前拥有者,确保同一个线程可以多次进入锁区域,而不会导致死锁。这是 Java 中许多同步类(如 ReentrantLock)的基础。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

SQLSTATE[42S22]: Column not found: 1054 Unknown column Color in field list

遇到 SQLSTATE[42S22]: Column not found: 1054 Unknown column Color in field list 错误,通常表示你在执行 SQL 语句时引用了一个不存在的列。这可能是由于拼写错误、表结构变更等原因导致的。 解决方法检查列名是否正确: 确认 Color 列是否存在,并且拼写正确。获取表结构…

P9752 [CSP-S 2023] 密码锁P8814 [CSP-J 2022] 解密

Guten Tag!Schn, dich zu sehen! 今天也是很懒惰的一天呢!所以今天三合一! 题目:[CSP-S 2023] 密码锁 题目描述 小 Y 有一把五个拨圈的密码锁。如图所示,每个拨圈上是从 $0$ 到 $9$ 的数字。每个拨圈都是从 $0$ 到 $9$ 的循环,即 $9$ 拨动一个位置后可以变成 $0$ 或 $8$,…

【STC15】实现printf()重定向的相关问题

本文前提:读者已经知道如何用STC15实现串口重定向的基础知识(大体思路和代码大意)。 如果不知道,请移步:《STC15单片机-串口打印》:https://blog.csdn.net/weixin_46251230/article/details/126679956问题1:uint8_t 数字增长显示错误 /* Private variables-------------…

解决wsl 安装出现Installing, this may take a few minutes… 时间长。且重新打开进入root用户问题

1. 现象 在安装wsl出现 Installing, this may take a few minutes… 等待时间过长,无法启动,或报错。且如果你重新打开终端,出现图二情况(直接进入root用户)。 很显然,你的系统已经正确安装,但是你却跳过了创建用户的步骤,因此,只需要创建一个新用户,并将其设定为默认…

数据库——DQL单表查询

DQL单表查询id name gender age score111111 刘一 女 20 NULL186222 陈二 男 30 90275933 张三 女 24 92266055 李十四 男 20 92134444 王五 女 18 92225573 赵十六 男 22 94一、简单查询(SELECT...FROM...) 1.查询所有字段(*) --SELECT * FROM 表名; SELECT * FROM class…

数据库——DDL数据库和数据表的基本操作

DDL 一、数据库的基本操作 1、创建(CREATE) --CREATE DATABASE/SCHEMA [IF NOT EXISTS] 表名[指定数据库的字符集]; --创建名为my的数据库 CREATE DATABASE my; CREATE SCHEMA my;--如果名为my的数据库不存在则创建,避免了当数据库存在而发生的错误 CREATE DATABASE IF NOT EXI…

安卓Android虚拟机分享及使用

不知道大家伙在安装安卓虚拟机时被各式各样的问题折磨过没,我在安装安卓虚拟机时,遇到的问题简直就像长江之水源源不断,就算是最后安装好了也会因为各式各样的原因无法进入启动桌面。 当我发现这个可以直接导入到电脑一键开启运行的虚拟机时,今天我必须分享给大家!话不多说…

PotPlayer(免费媒体播放器) v1.7.22233.0 多语便携版

概述 PotPlayer是一款由韩国企业Daum开发的免费媒体播放器,它提供了丰富的功能和特点,使其成为许多用户的首选播放器。 软件功能 支持多种音视频格式:PotPlayer支持大多数常见的音视频格式,包括MP4、AVI、MKV、MOV、FLV、MP3、WAV等。高质量的音视频播放:PotPlayer采用了…