备注:博文仅仅是学习过程中的零散记录,后期整理。

AbstractQueuedSynchronizer的简单介绍可以网上搜索,简单了解字段作用。

示例代码,分析获取锁的过程:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class AQS {
public static void main(String[] args) { Lock lock = new ReentrantLock(); lock.lock(); // do something lock.unlock(); } }

调用lock方法,然后间接调用:

    /**
* Sync object for non-fair locks
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L; /**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))//更新state的状态值,state是用来记录获取锁的情况。state=0的话则锁没有人获取,当大于0时候表示锁被获取。重入次数。
setExclusiveOwnerThread(Thread.currentThread()); //AQS的exclusiveOwnerThread成员,记录当前获取锁的线程
else
acquire(1);
} protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}

调用如上代码的lock方法,其中的compareAndSetState调用底层操作系统的CAS方法,是一个原子操作。到此就完成了获取锁。

接下来看看重入锁申请过程,java.util.concurrent.locks.ReentrantLock.Sync.nonfairTryAcquire(int):

        /**
* Performs non-fair tryLock. tryAcquire is
* implemented in subclasses, but both need nonfair
* try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread(); //当获取重入锁时候,判断当前线程和之前申请锁的线程是否是一个?如果不是一个的话则直接返回false
int c = getState();
if (c == 0) { //第一次获取锁时,state为0
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
      //如果不是第一次的话,则重入锁
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires; //acquires参数每一次获取锁时候,参数acquires都为1,代表依次获取锁。nextc是当前一共获取锁的次数
if (nextc < 0) // overflow ,重入次数过多,导致大于Int最大值溢出,抛异常
throw new Error("Maximum lock count exceeded");
setState(nextc);//更新state状态值
return true; //获取锁成功
}
return false;
}

接下来看看释放锁的过程,java.util.concurrent.locks.ReentrantLock.Sync.tryRelease(int):

      //unlock最终调用这个方法释放锁
protected final boolean tryRelease(int releases) {
int c = getState() - releases; //判断state的值,释放锁进行一次减1操作
if (Thread.currentThread() != getExclusiveOwnerThread())//判断释放锁的线程和当初获取锁的线程是否是一个线程,不是的话则抛异常
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {//如果锁已经彻底释放,则将获取锁的线程设置为null
free = true;
setExclusiveOwnerThread(null);
}
setState(c);//更新state的状态
return free;
}

重入锁的释放同上。

Java中关于AbstractQueuedSynchronizer的入门(一)的更多相关文章

  1. Java中关于AbstractQueuedSynchronizer的入门(二)

    AQS是一个同步器的基础类,里面的关键字段: //如下关键字段都是volatile类型 /** * Head of the wait queue, lazily initialized. Except ...

  2. Java中的IO流 - 入门篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的IO流-入门篇>,希望对大家有帮助,谢谢 由于Java的IO类有很多,这就导致我刚开始学的时候,感觉很乱,每次用到都是上网搜,结果 ...

  3. Java中的集合List - 入门篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的集合List - 入门篇>,希望对大家有帮助,谢谢 简介 说实话,Java中的集合有很多种,但是这里作为入门级别,先简单介绍第一种 ...

  4. Java中的映射Map - 入门篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的映射Map - 入门篇>,希望对大家有帮助,谢谢 简介 前面介绍了集合List,这里开始简单介绍下映射Map,相关类如下图所示 正 ...

  5. Java中的集合Set - 入门篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的集合Set - 入门篇>,希望对大家有帮助,谢谢 简介 前面介绍了集合List,映射Map,最后再简单介绍下集合Set,相关类如下 ...

  6. Java中Redis的简单入门

    1.下载redis服务器端程序: 在redis.io官网完成服务器端程序下载:可下载安装版或解压版,此处我下载的是解压版,下载完成后解压. 2.配置redis密码,开启redis服务端 在redis. ...

  7. Java中Redis简单入门

    Redis是一个开源的,先进的 key-value 存储可用于构建高性能,可扩展的 Web 应用程序的解决方案. Redis官方网网站是:http://www.redis.io/,如下: Redis ...

  8. 【JAVA零基础入门系列】Day5 Java中的运算符

    运算符,顾名思义就是用于运算的符号,比如最简单的+-*/,这些运算符可以用来进行数学运算,举个最简单的栗子: 已知长方形的长为3cm,高为4cm,求长方形的面积. 好,我们先新建一个项目,命名为Rec ...

  9. 【JAVA零基础入门系列】Day9 Java中的那个大数值

    什么是大数值?用脚趾头想也知道,当然是"大"的数值(233).Java中有两个用于表示大数值的类,BigInteger和BigDecimal,那到底能表示多大的数值呢?理论上,可以 ...

随机推荐

  1. Shell 数组定义与获取

    Shell 数组 bash支持一维数组(不支持多维数组),并且没有限定数组的大小. 类似与 C 语言,数组元素的下标由 0 开始编号.获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于 ...

  2. Groovy学习笔记(1)读取CSV文件

      本篇分享讲展示如何在Groovy中读取CSV文件.   我们要读取的CSV文件foo.csv的内容如下:   Groovy代码如下: //import packages import java.i ...

  3. ModBus通信协议的【主从模式】

    主从模式 (1) 至少且只有一个主机,其他的都是从机 (2) 不管任何时候,从机都不能主动向主机发送数据 (3) 主机具有访问从机的权限,从机不可以主动访问从机,任何一次数据交换,都要由主机发起 (4 ...

  4. mysql游标中使用临时表

    有时候需我们要组合几张表的数据,在存储过程中,经过比较复杂的运算获取结果直接输出给调用方,比如符合条件的几张表的某些字段的组合计算,mysql临时表可以解决这个问题. 所谓临时表:只有在当前连接情况下 ...

  5. 【Java】HashMap源码分析——基本概念

    在JDK1.8后,对HashMap源码进行了更改,引入了红黑树.在这之前,HashMap实际上就是就是数组+链表的结构,由于HashMap是一张哈希表,其会产生哈希冲突,为了解决哈希冲突,HashMa ...

  6. java Spring 各版本jar包下载地址

    http://repo.spring.io/simple/libs-release-local/org/springframework/

  7. SD从零开始62-63,不完全日志,业务伙伴及业务伙伴确定

    [原创] SD从零开始62 不完全日志 不完全日志Incompletion log 一个不完全日志是销售凭证中对你公司重要的而还没有在系统中输入的所有数据的清单: 你可以在配置中为不完全日志定义这些数 ...

  8. Android NDK编译之undefined reference to 'JNI_CreateJavaVM'

    利用Android NDK编译动态库,在C文件中调用了两个JNI函数:JNI_GetDefaultJavaVMInitArgs和JNI_CreateJavaVM.编译的时候始终报以下错误: XXX: ...

  9. Android深入四大组件(八)广播的注册、发送和接收过程

    前言 我们接着来学习Android四大组件中的BroadcastReceiver,广播主要就是分为注册.接收和发送过程.建议阅读此文前请先阅读Android深入理解四大组件系列的文章,知识重复的部分, ...

  10. (后端)Java新人入职——配置环境及安装开发工具(完全)

    转自csdn:执笔记忆的空白 很多新人对于进入新公司,相关工具的安装和环境变量的设定很苦恼.又苦于没有完整的配置开发环境的资料,我这里写一篇操作步骤的案例, 至少让你能把开发工具安装起来,并实用起来, ...