并发之AQS原理(一)

如果说每一个同步的工具各有各的强大,那么这个强大背后是一个相同的动力,它就是AQS.

AQS是什么

AQS是指java.util.concurrent.locks包里的AbstractQueuedSynchronizer类,抽象的FIFO队列式的同步器,AQS定义了一套多线程访问共享资源的同步器框架

在了解AQS之前先了解下

先入先出队列(First Input First Output,FIFO)这是一种传统的按序执行方法,先进入的指令先完成并引退,跟着才执行第二条指令。

就是通常情况下的排队。

AQS简单的来说就是使用了一个共享变量来同步状态,该状态由子类去维护,而AQS框架做的是

  • 线程阻塞队列的维护。
  • 线程阻塞和唤醒。

    共享变量的操作通过Unsafe类提供的CAS操作完成的。AQS类主要使用的就是2个方法 acquirerelease

acquire(获得锁):返回true则放线程成继续执行,否则将线程加入等待队列中,等待唤醒.

release(释放锁):用于释放锁。释放当前线程队列中的头结点,然后调用唤醒下一个结点的方法。

AQS的简单使用

一般的来说AQS的使用方式是继承,用的是模板方法模式。

下面我们来用一个简单的AQS实现来逐步讲解下AQS的原理。

EasyLock简单实现AQS

首先实现一个简单的锁就叫EasyLock吧

/**
* 简单不可重入锁实现
*
*/
public class EasyLock extends AbstractQueuedSynchronizer { /**
* 锁定
*/
public void lock(){
acquire(1);
} /**
* 尝试锁定
*/
public boolean tryLock(){
return tryAcquire(1);
} /**
* 解锁
*/
public void unlock(){
release(1);
} /**
* 是否为锁定
*/
public boolean isLocked(){
return isHeldExclusively();
} /**
* 尝试获取锁
*/
@Override
protected boolean tryAcquire(int arg) {
if(compareAndSetState(0,1)){
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
} /**
* 尝试释放锁
*/
@Override
protected boolean tryRelease(int arg) {
setExclusiveOwnerThread(null);
setState(0);
return true;
}
}

测试


public class AqsExampleDemo {
private static final int clientTotal = 30000;
private static int count = 0; public static void main(String[] args) throws InterruptedException {
final EasyLock easyLock = new EasyLock();
ExecutorService executorService = Executors.newCachedThreadPool();
CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal; i++) {
executorService.execute(() -> {
try {
easyLock.lock();
count++;
easyLock.unlock();
} catch (Exception e) {
e.printStackTrace();
}
countDownLatch.countDown();
});
} countDownLatch.await();
System.out.println("统计次数:" + count); }
}

可以看出打印的结果是5000,并没有出现并发问题。

总结

可以看出AQS的使用非常简单几乎只需要重写 tryAcquire、tryRelease就可以自己实现一个锁。

下一篇我们讲解下AQS中底层的CLH队列是如何保证其并发性的。

并发之AQS原理(一) 原理介绍简单使用的更多相关文章

  1. 并发之AQS原理(二) CLH队列与Node解析

    并发之AQS原理(二) CLH队列与Node解析 1.CLH队列与Node节点 就像通常医院看病排队一样,医生一次能看的病人数量有限,那么超出医生看病速度之外的病人就要排队. 一条队列是队列中每一个人 ...

  2. Java并发之AQS原理解读(三)

    上一篇:Java并发之AQS原理解读(二) 前言 本文从源码角度分析AQS共享锁工作原理,并介绍下使用共享锁的子类如何工作的. 共享锁工作原理 共享锁与独占锁的不同之处在于,获取锁和释放锁成功后,都会 ...

  3. Java并发之AQS原理解读(二)

    上一篇: Java并发之AQS原理解读(一) 前言 本文从源码角度分析AQS独占锁工作原理,并介绍ReentranLock如何应用. 独占锁工作原理 独占锁即每次只有一个线程可以获得同一个锁资源. 获 ...

  4. Java并发之AQS原理解读(一)

    前言 本文简要介绍AQS以及其中两个重要概念:state和Node. AQS 抽象队列同步器AQS是java.util.concurrent.locks包下比较核心的类之一,包括AbstractQue ...

  5. 并发之AQS原理(三) 如何保证并发

    并发之AQS原理(三) 如何保证并发 1. 如何保证并发 AbstractQueuedSynchronizer 维护了一个state(代表了共享资源)和一个FIFO线程等待队列(多线程竞争资源被阻塞时 ...

  6. 粗略介绍Java AQS的实现原理

    本文转自 http://www.importnew.com/24006.html 感谢作者 对我很有帮助 ①引言 AQS是JDK1.5提供的一个基于FIFO等待队列一个同步器的基础框架,java中的同 ...

  7. 并发——抽象队列同步器AQS的实现原理

    一.前言   这段时间在研究Java并发相关的内容,一段时间下来算是小有收获了.ReentrantLock是Java并发中的重要部分,所以也是我的首要研究对象,在学习它的过程中,我发现它是基于抽象队列 ...

  8. JVM垃圾回收器原理及使用介绍

    JVM垃圾回收器原理及使用介绍 垃圾收集基础 引用计数法(Reference Counting) 标记-清除算法(Mark-Sweep) 复制算法(Copying) 标记-压缩算法(Mark-Comp ...

  9. 透过 ReentrantLock 分析 AQS 的实现原理

    对于 Java 开发者来说,都会碰到多线程访问公共资源的情况,这时候,往往都是通过加锁来保证访问资源结果的正确性.在 java 中通常采用下面两种方式来解决加锁得问题: synchronized 关键 ...

随机推荐

  1. 弹指之间 -- Polychord

    CHAPTER 19 复合和弦 Polychord 示例歌曲:爱很简单,恰是你的温柔

  2. java中各种时间公式

    /** * 返回当前时间 * * @return 返回当前时间 */ public static Date getCurrentDateTime() { java.util.Calendar calN ...

  3. 函数和常用模块【day04】:内置函数(八)

    一.常用内置函数 1.表格 二.内置函数详情(1-10) 1.abs(x) 功能:取数的绝对值 1 2 >>> abs(-1)  #取-1的绝对值 1 2.all(iterable) ...

  4. C#网络编程之进程管理

    这里是视频讲解地址: 这里是代码: using System; using System.Collections.Generic; using System.Linq; using System.Ne ...

  5. Kafka记录-Kafka简介与单机部署测试

    1.Kafka简介 kafka-分布式发布-订阅消息系统,开发语言-Scala,协议-仿AMQP,不支持事务,支持集群,支持负载均衡,支持zk动态扩容 2.Kafka的架构组件 1.话题(Topic) ...

  6. (cx_Oracle.DatabaseError) DPI-1047: 64-bit Oracle Client library cannot be loaded: "libclntsh.so: cannot open shared object file: No such file or directory"

    打开https://oracle.github.io/odpi/doc/installation.html 官方相关如下 Oracle Instant Client RPM¶ To run ODPI- ...

  7. Hibernate_day03

    一.今天内容 0 列表功能实现 1 表与表之间关系回顾 (1)一对多(客户和联系人) (2)多对多(用户和角色) 2 hibernate一对多操作 (1)一对多映射配置 (2)一对多级联保存 (3)一 ...

  8. go通过swig封装、调用c++共享库的技术总结

    go通过swig封装.调用c++共享库的技术总结 @(知识记录) 1 简介 最近在研究golang,希望能对目前既有的python服务做一些优化,这些服务目前已经占用了6-7台机器.选择golang的 ...

  9. 第17月第7天 iOS 数组越界,防Crash处理

    1. 上面方法已经可以避免crash,为了避免冗余的代码,写一个NSArray的分类,利用runtime替换NSArray的对象方法objectAtIndex:,在这里进行判断,捕获异常: #impo ...

  10. 第16月第9天 opengl glCltDispatchTable

    1.glCltDispatchTable typedef struct _GLTEBINFO { // glCltDispatchTable must be the first field for t ...