博客
关于我
ReentrantLock 源码分析 - AbstractQueuedSynchronizer 详解(一)
阅读量:480 次
发布时间:2019-03-06

本文共 1964 字,大约阅读时间需要 6 分钟。

前言

上一篇文章介绍了AbstractQueuedSynchronizer (AQS)的基本概念及其在Java并发编程中的作用。本文将基于JDK 8的源码,深入分析AQS及其在ReentrantLock中的应用。阅读本文前,建议了解共享锁和独占锁的基本概念。

正文

上一篇文章提到CountDownlatch、ReentrantLock、ReentrantReadWriteLock以及Semaphore等并发工具类都基于AQS实现。为了支持这些功能,AQS需要具备高度灵活和通用的功能。例如:

  • ReentrantLock(独占锁)通过调用AQS的acquire方法获取独占资源。
  • ReentrantReadWriteLock(共享锁)通过调用AQS的acquireShared方法获取共享资源。
  • 这些方法均呼吁了compareAndSetState方法来执行CAS操作。

虽然上述只是两个类的区别,但Java.util.concurrent包中包含多种工具类,因此我们无需全面理解AQS的所有功能。接下来,我们将重点分析AQS在ReentrantLock中的作用。


1. Node类

Node类是AQS的内部类,主要用于管理队列中的节点。其属性包括:

  • prevnext:分别表示前驱和后驱指针。
  • thread:存储当前线程标识。
  • SHARED:标记当前线程因抢夺共享资源而进入队列。
  • EXCLUSIVE:标记当前线程因抢夺独占资源而进入队列。
  • waitStatus:表示当前线程的等待状态,可选值包括CANCELLED、CONDITION、SIGNAL和PROPAGATE。

AQS是一个双向队列,队列中的元素是Node对象。


2. AQS的核心属性

AQS维护以下关键属性:

  • headtail:分别指向队列的头节点和尾节点。
  • state:表示当前锁的状态。例如,在ReentrantLock中,state即为重入次数。

3. AQS的核心方法

AQS提供了几个关键方法:

  • acquire(int arg):尝试获取独占资源。当获取失败时,将当前线程放入队列并阻塞。
  • release(int arg):释放独占资源,并唤醒队列中的线程。
  • compareAndSetState(long expect, long update):通过CAS操作来更新状态。

3.1 acquire方法

acquire方法的大致逻辑如下:

public final void acquire(int arg) {    if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) {        selfInterrupt();    }}
  • tryAcquire尝试获取锁,如果成功则返回true,否则返回false。
  • acquireQueued将当前线程挂入队列并阻塞。
  • selfInterrupt在获取失败后唤醒当前线程。

3.2 release方法

release方法的大致逻辑如下:

public final boolean release(int arg) {    if (tryRelease(arg)) {        Node h = head;        if (h != null && h.waitStatus != 0) {            unparkSuccessor(h);        }        return true;    }    return false;}
  • tryRelease尝试释放锁,成功时返回true,否则返回false。
  • unparkSuccessor唤醒队列中的线程,并调用LockSupport.unpark方法。

3.3 compareAndSetState方法

compareAndSetState方法通过unsafe类的native方法实现CAS操作。例如:

protected final boolean compareAndSetState(long expect, long update) {    return unsafe.compareAndSwapLong(this, stateOffset, expect, update);}

总结

AQS是一个高度灵活的同步设施,作为许多并发工具类(如ReentrantLock)的基础。它通过双向队列管理线程,并支持CAS操作来实现高效的信号传递。当多个线程竞争锁时,未成功获取锁的线程会被放入队列,直到锁被释放并唤醒。AQS的引用使相关锁类能够支持复杂的并发场景,具体实现方式需结合各类的具体需求来定制。

转载地址:http://jgpdz.baihongyu.com/

你可能感兴趣的文章
Prismix:Prisma 架构混合器,为复杂项目而生
查看>>
pritunl服务安装及配置
查看>>
Private Destructor
查看>>
private和protected能同时修饰成员变量吗_天天用注解你了解注解是怎么实现的吗?...
查看>>
privoxy Invalid header received from client.
查看>>
Privoxy代码下载
查看>>
Probabilistic-Programming-and-Bayesian-Methods-for-Hackers
查看>>
pytorch中的求和函数sum(axis=x)解释
查看>>
Problem F: 质心算法
查看>>
Problem N HDU 2612 Find a way (两次BFS求最值)
查看>>
Process /usr/libexec/gdu-notification-daemon was killed by signal 6 (SIGABRT)
查看>>
process.env.VUE_APP_BASE_API 获取不到
查看>>
Process.run() 和 Process.start() 之间的区别
查看>>
Processes
查看>>
Processing通过编程实现艺术设计_实现艺术和现实的交互---数据设计分析002
查看>>
ProcessOnLoading
查看>>
SpringBoot中集成screw(螺丝钉)实现数据库表结构文档生成
查看>>
PROFINET 模拟器使用教程
查看>>
Program type already present: android.support.v4.widget.EdgeEffectCompat
查看>>
PyTorch中文版官方教程来啦(附下载)
查看>>