在上节中解析了AbstractQueuedSynchronizer(AQS)中独占模式对同步状态获取和释放的实现过程。本节将会对共享模式的同步状态获取和释放过程做一个解析。上一节提到了独占模式和共享模式的区别,最主要的区别就是在同一时刻能否有多个线程同时获取到同步状态。

  1).共享模式同步状态的获取

  这个方法同独占模式获取同步状态的acquire方法一样,同样也是一个模板方法,我们简要回顾一下独占模式下获取同步状态的acquire方法:

//AbstractQueuedSynchronizer#acquire
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) //获取锁(tryAcquire)->构造节点(addWaiter)->加入队列(addWaiter)->自旋获取锁(acquireQueued)
selfInterrupt(); //中断当前线程
}
//AbstractQueuedSynchronizer#acquireShared
public final void acquireShared(int arg) {
if (tryAcquireShared(arg)) //获取锁,由子类具体实现
doAcquireShared(arg);
}
private void doAcquireShared(int arg) {
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null;
if (inerrupted)
selfInterrupt();
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(arg);
}
}

共享模式下获取同步状态的自旋过程和独占模式大致相同,从代码实现角度来看不同的是共享模式下把线程构造节点加入队列,以及在获取同步状态后中断当前线程都放到了同一个方法里doAcquireShared。共享模式同样也是只有在是其前驱节点是头结点的时候才会尝试获取同步状态,调用tryAcquireShared获取同步状态成功后会返回大于等于0的数,这个时候将会执行setHeadAndPropagate方法,这个方法首先会将当前获取同步状态的这个线程置为头节点(同独占模式一样),但在将当前线程置为头节点过后,又做了一部分操作,其代码如下:

private void setHeadAndPropagate(Node node, int propagate) {
Node h = head;
setHead(node); //将当前获取到同步状态的线程节点置为头节点
if (propagate > 0 || h == null || h.waitStatus < 0) { //唤醒后继节点
Node s = node.next;
if (s == null || s.isShared())
doReleaseShared(); //唤醒后继节点,因为是共享模式,所以允许多个线程同时获取同步状态
}
}

  在doReleaseShared方法中,首先便利队列中的所有节点,如果节点状态为SIGNAL,则把SIGNAL状态置为0(初始状态),并调用unparkSuccessor把该节点的后继节点唤醒,如果该节点的状态为0,则把状态置为PROPAGATE。

2).共享模式同步状态的释放

  该方法的实现同独占模式类似,也是一个模板方法,具体的释放实现由子类自定义,在成功释放同步状态后将会唤醒后继节点:

public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) { //释放同步状态
doReleaseShared(); //唤醒后继节点
return true;
}
return false;
}

  以上就是AQS中的共享模式对同步状态的获取与释放,在有了独占模式的分析过后,对共享模式的分析就显得要轻松得多。下一节将会继续探讨AbstractQueuedSynchronizer类中具体的一些细节问题。

3.从AbstractQueuedSynchronizer(AQS)说起(2)——共享模式的锁获取与释放的更多相关文章

  1. 2.从AbstractQueuedSynchronizer(AQS)说起(1)——独占模式的锁获取与释放

    首先我们从java.util.concurrent.locks包中的AbstraceQueuedSynchronizer说起,在下文中称为AQS. AQS是一个用于构建锁和同步器的框架.例如在并发包中 ...

  2. Java并发系列[3]----AbstractQueuedSynchronizer源码分析之共享模式

    通过上一篇的分析,我们知道了独占模式获取锁有三种方式,分别是不响应线程中断获取,响应线程中断获取,设置超时时间获取.在共享模式下获取锁的方式也是这三种,而且基本上都是大同小异,我们搞清楚了一种就能很快 ...

  3. 4.从AbstractQueuedSynchronizer(AQS)说起(3)——AQS结语

    前两节的内容<2.从AbstractQueuedSynchronizer(AQS)说起(1)——独占模式的锁获取与释放> .<3.从AbstractQueuedSynchronize ...

  4. AbstractQueuedSynchronizer AQS框架源码剖析

    一.引子 Java.util.concurrent包都是Doug Lea写的,来混个眼熟 是的,就是他,提出了JSR166(Java Specification RequestsJava 规范提案), ...

  5. 8.初识Lock与AbstractQueuedSynchronizer(AQS)

    1. concurrent包的结构层次 在针对并发编程中,Doug Lea大师为我们提供了大量实用,高性能的工具类,针对这些代码进行研究会让我们对并发编程的掌握更加透彻也会大大提升我们队并发编程技术的 ...

  6. 初识Lock与AbstractQueuedSynchronizer(AQS)

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  7. AQS源码深入分析之共享模式-你知道为什么AQS中要有PROPAGATE这个状态吗?

    本文基于JDK-8u261源码分析 本篇文章为AQS系列文的第二篇,前文请看:[传送门] 第一篇:AQS源码深入分析之独占模式-ReentrantLock锁特性详解 1 Semaphore概览 共享模 ...

  8. Java并发基础之AbstractQueuedSynchronizer(AQS)

    AbstractQueuedSynchronizer同步器是实现JUC核心基础组件,因为 定义了一套多线程访问共享资源的同步器框架.前面几篇文章中JUC同步工具中都利用AQS构建自身的阻塞类.AQS解 ...

  9. AbstractQueuedSynchronizer 原理分析 - 独占/共享模式

    1.简介 AbstractQueuedSynchronizer (抽象队列同步器,以下简称 AQS)出现在 JDK 1.5 中,由大师 Doug Lea 所创作.AQS 是很多同步器的基础框架,比如 ...

随机推荐

  1. 微信小程序-实战巩固(二)

    刚刚写了小程序入门没几天,小程序就开放个人开发者资格,感觉为我而来啊 \(≧▽≦)/.迫不及待的去注册,准备将之前的处女作传上去体验一把,结果卡在了服务器配置上:免费的果然不靠谱/(ㄒoㄒ)/~~,后 ...

  2. Realm数据持久化方案的简单介绍和使用(二)

    接上篇... 4. 可空属性&默认值&忽略属性 默认情况下, 属性值可空, 如果强制要求某个属性非空, 可以使用如下方法: 遵循协议方法 + (NSArray *)requiredPr ...

  3. Vue.js 学习笔记 一

    本文的Demo和源代码已放到GitHub,如果您觉得本篇内容不错,请点个赞,或在GitHub上加个星星! https://github.com/zwl-jasmine95/Vue_test 以下所有知 ...

  4. Angular4.0.0发布总览文章

    翻译自angular.io上的关于4.0.0版本发布的文章,内容主要是介绍了4.0.0版本下的改进以及接下来还会有的其他更新,4.0.0其实已经出来好多天了,截止目前都已经到了4.0.1版本了,这也是 ...

  5. 浅析Java中synchronized与static synchronized

    synchronized关键字 synchronized是进行同步处理而保证线程安全.在一个方法中,如果是方法内的私有变量,那个这个变量是线程安全的,但是类中的实例变量是可能会出现线程安全问题的,当多 ...

  6. MySQL学习笔记(一)—数据库基础

    一.数据库概述 1.数据库的组织结构      (1)数据库就是用来存放信息的仓库.      (2)数据库里的数据集合都存放在数据表(table)里.      (3)数据表由数据行(row)和数据 ...

  7. DOM 待编辑

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. 轻量级操作系统FreeRTOS的内存管理机制(一)

    本文由嵌入式企鹅圈原创团队成员朱衡德(Hunter_Zhu)供稿. 近几年来,FreeRTOS在嵌入式操作系统排行榜中一直位居前列,作为开源的嵌入式操作系统之一,它支持许多不同架构的处理器以及多种编译 ...

  9. 【stm32】时钟树解析

    有时候会突然忘了这个重要的时钟树,这里转载一个比较好的,以防忘记. STM32时钟系统 在STM32中,有五个时钟源,为HSI.HSE.LSI.LSE.PLL. ①HSI是高速内部时钟,RC振荡器,频 ...

  10. MyBatis-plus 代码自动生成器

    MyBatis-plus  代码自动生成器 1.添加pom文件依赖 <!-- Mybatis-Plus 自动生成实体类--> <dependency> <groupId& ...