博客
关于我
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/

你可能感兴趣的文章
No module named 'crispy_forms'等使用pycharm开发
查看>>
No module named cv2
查看>>
No module named tensorboard.main在安装tensorboardX的时候遇到的问题
查看>>
No module named ‘MySQLdb‘错误解决No module named ‘MySQLdb‘错误解决
查看>>
No new migrations found. Your system is up-to-date.
查看>>
No qualifying bean of type XXX found for dependency XXX.
查看>>
No resource identifier found for attribute 'srcCompat' in package的解决办法
查看>>
no session found for current thread
查看>>
No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android
查看>>
NO.23 ZenTaoPHP目录结构
查看>>
NO32 网络层次及OSI7层模型--TCP三次握手四次断开--子网划分
查看>>
NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
查看>>
Node JS: < 一> 初识Node JS
查看>>
Node-RED中使用JSON数据建立web网站
查看>>
Node-RED中使用json节点解析JSON数据
查看>>
Node-RED中使用node-random节点来实现随机数在折线图中显示
查看>>
Node-RED中使用node-red-browser-utils节点实现选择Windows操作系统中的文件并实现图片预览
查看>>
Node-RED中使用node-red-node-ui-iframe节点实现内嵌iframe访问其他网站的效果
查看>>
Node-RED中使用Notification元件显示警告讯息框(温度过高提示)
查看>>
Node-RED中实现HTML表单提交和获取提交的内容
查看>>