AQS是JUC中很多同步组件的构建基础,简单来讲,它内部实现主要是状态变量state和一个FIFO队列来完成,同步队列的头结点是当前获取到同步状态的结点,获取同步状态state失败的线程,会被构造成一个结点(或共享式或独占式)加入到同步队列尾部(采用自旋CAS来保证此操作的线程安全),随后线程会阻塞;释放时唤醒头结点的后继结点,使其加入对同步状态的争夺中。

  AQS为我们定义好了顶层的处理实现逻辑,我们在使用AQS构建符合我们需求的同步组件时,只需重写tryAcquire,tryAcquireShared,tryRelease,tryReleaseShared几个方法,来决定同步状态的释放和获取即可,至于背后复杂的线程排队,线程阻塞/唤醒,如何保证线程安全,都由AQS为我们完成了,这也是非常典型的模板方法的应用。AQS定义好顶级逻辑的骨架,并提取出公用的线程入队列/出队列,阻塞/唤醒等一系列复杂逻辑的实现,将部分简单的可由使用者决定的操作逻辑延迟到子类中去实现。

package com.abstractqueuesynchronizer;

import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class SelfAbstractQueueSynchronizer {

    //继承AbstractQueuedSynchronizer类
private static class Syn extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 1L; //是否拥有锁
protected boolean isHeldExclusively() {
return getState() == 1;
} //获取锁
public boolean tryAcquire(int acquires) {
if(compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
} //释放所
protected boolean tryRelease(int releases) {
if(getState() == 0)
throw new IllegalMonitorStateException();
setExclusiveOwnerThread(null);
setState(0);
return true;
}
} private final Syn syn = new Syn(); public void lock() {
syn.acquire(1);
} public boolean tryLock() {
return syn.tryAcquire(1);
} public void unlock() {
syn.release(1);
} public boolean isLocked() {
return syn.isHeldExclusively();
}
}

测试

package com.abstractqueuesynchronizer;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier; public class Main { private static CyclicBarrier barrier = new CyclicBarrier(31);
private static int a = 0;
private static SelfAbstractQueueSynchronizer test = new SelfAbstractQueueSynchronizer(); public static void main(String[] args) throws InterruptedException, BrokenBarrierException { for(int i = 0; i < 30; i++) {
Thread t = new Thread(new Runnable(){ @Override
public void run() {
for(int i = 0; i < 1000; i++) {
unlockIncrement();
}
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();;
}
} });
t.start();
} barrier.await();
System.out.println("unlock model a= " + a); System.out.println("##########################"); barrier.reset();
a = 0;
for(int i = 0; i < 30; i++) {
Thread t = new Thread(new Runnable(){
@Override
public void run() {
for(int i = 0; i < 1000; i++ ) {
lockIncrement();
} try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
} });
t.start();
} barrier.await();
System.out.println("lock model a= " + a); } public static void unlockIncrement() {
a++;
} public static void lockIncrement() {
test.lock();
a++;
test.unlock();
} }

AbstractQueuedSynchronizer简单使用的更多相关文章

  1. JUC锁框架_AbstractQueuedSynchronizer详细分析

      AQS是JUC锁框架中最重要的类,通过它来实现独占锁和共享锁的.本章是对AbstractQueuedSynchronizer源码的完全解析,分为四个部分介绍: CLH队列即同步队列:储存着所有等待 ...

  2. AbstractQueuedSynchronizer的简单分析

    说明:本作者是文章的原创作者,转载请注明出处:本文地址:http://www.cnblogs.com/qm-article/p/7955781.html 一.AbstractQueuedSynchro ...

  3. AbstractQueuedSynchronizer的简单介绍

    AbstractQueuedSynchronizer简称为AQS.大多数开发者不会直接使用AQS,标准同步器类的集合能够满足绝大多数情况的需求. 1.AbstractQueuedSynchronize ...

  4. Java并发基础框架AbstractQueuedSynchronizer初探(ReentrantLock的实现分析)

    AbstractQueuedSynchronizer是实现Java并发类库的一个基础框架,Java中的各种锁(RenentrantLock, ReentrantReadWriteLock)以及同步工具 ...

  5. 并发编程 20—— AbstractQueuedSynchronizer 深入分析

    Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...

  6. Java Concurrent之 AbstractQueuedSynchronizer

    ReentrantLock/CountDownLatch/Semaphore/FutureTask/ThreadPoolExecutor的源码中都会包含一个静态的内部类Sync,它继承了Abstrac ...

  7. Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析

    经过前面几篇文章的铺垫,今天我们终于要看看AQS的庐山真面目了,建议第一次看AbstractQueuedSynchronizer 类源码的朋友可以先看下我前面几篇文章: <Java并发包源码学习 ...

  8. 通过ReentrantLock源代码分析AbstractQueuedSynchronizer独占模式

    1. 重入锁的概念与作用       reentrant 锁意味着什么呢?简单来说,它有一个与获取锁相关的计数器,如果已占有锁的某个线程再次获取锁,那么lock方法中将计数器就加1后就会立刻返回.当释 ...

  9. 从一个简单的Java单例示例谈谈并发

    一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这么写 public class UnsafeLazyInitiallization { private static Un ...

随机推荐

  1. Dump文件的生成

    一.Windows系统的任务管理器里抓dump 启动任务管理器,选中某个进程,右键,弹出菜单"创建转储文件" 注意事项: 当你在64位Windows系统上抓32位进程的dmup文件 ...

  2. 19 如何在String和Byte[]对象之间进行转换?

  3. 如何将数组中的元组包转化为字典通过json序列化给前端

  4. 关于富文本复制word,里面掺杂图片上传的问题

    图片的复制无非有两种方法,一种是图片直接上传到服务器,另外一种转换成二进制流的base64码目前限chrome浏览器使用首先以um-editor的二进制流保存为例:打开umeditor.js,找到UM ...

  5. BZOJ 2729: [HNOI2012]排队 排列组合 + 高精度

    Description 某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检.他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不 ...

  6. 学习日记7、mvc +easyui datagrid excel上传

    1.首先获取datagrid所有行的数据 var rows = $("#List").datagrid("getRows"); 2.进行数据转换转化成JSON格 ...

  7. django搭建一个小型的服务器运维网站-用户登陆与session

    目录 项目介绍和源码: 拿来即用的bootstrap模板: 服务器SSH服务配置与python中paramiko的使用: 用户登陆与session; 最简单的实践之修改服务器时间: 查看和修改服务器配 ...

  8. docker 部署ftp

    1.搜索ftp镜像 docker search vsftpd 2.拉取ftp镜像 docker pull fauria/vsftpd 3.启动ftpdocker docker run -d -v /h ...

  9. delphi 获取文件的最新修改时间 http://www.delphitop.com/html/wenjian/64.html

    delphi 获取文件的最新修改时间 作者:admin 来源:未知 日期:2010/1/28 13:15:22 人气:1054 标签: QQ空间新浪微博腾讯微博腾讯朋友QQ收藏百度空间百度贴吧更多0 ...

  10. 为什么有mac地址还学要有IP地址??

    历史原因:早期的以太网只有集线器 ,没有交换机,所以发出去的包能被以太网内的所有机器监听到,因此要附带上MAC地址,每个机器只需要接受与自己MAC地址相匹配的包. 个人感觉上面的说法并不是太准确.找明 ...