博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java并发包源码学习之AQS框架(一)概述
阅读量:7201 次
发布时间:2019-06-29

本文共 2920 字,大约阅读时间需要 9 分钟。

AQS其实就是java.util.concurrent.locks.AbstractQueuedSynchronizer这个类。 阅读Java的并发包源码你会发现这个类是整个java.util.concurrent的核心之一,也可以说是阅读整个并发包源码的一个突破口。

比如读ReentrantLock的源码你会发现其核心是它的一个内部类Sync:

 

整个包中很多类的结构都是如此,比如Semaphore,CountDownLatch都有一个内部类Sync,而所有的Sync都是继承自AbstractQueuedSynchronizer。 所以说想要读懂Java并发包的代码,首先得读懂这个类。

AQS简核心是通过一个共享变量来同步状态,变量的状态由子类去维护,而AQS框架做的是:

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

共享变量的修改都是通过Unsafe类提供的CAS操作完成的。AbstractQueuedSynchronizer类的主要方法是acquirerelease,典型的模板方法, 下面这4个方法由子类去实现:

protected boolean tryAcquire(int arg)protected boolean tryRelease(int arg)protected int tryAcquireShared(int arg)protected boolean tryReleaseShared(int arg)

acquire方法用来获取锁,返回true说明线程获取成功继续执行,一旦返回false则线程加入到等待队列中,等待被唤醒,release方法用来释放锁。 一般来说实现的时候这两个方法被封装为lockunlock方法。

下面的SimpleLock类实现了一个最简单非重入的互斥锁的功能,实际上它就是ThreadPoolExecutor$Worker的实现(以后的文章会提到这个类)。

class SimpleLock extends AbstractQueuedSynchronizer {    private static final long serialVersionUID = -7316320116933187634L;    public SimpleLock() {    }    protected boolean tryAcquire(int unused) {        if (compareAndSetState(0, 1)) {            setExclusiveOwnerThread(Thread.currentThread());            return true;        }        return false;    }    protected boolean tryRelease(int unused) {        setExclusiveOwnerThread(null);        setState(0);        return true;    }    public void lock() {        acquire(1);    }    public boolean tryLock() {        return tryAcquire(1);    }    public void unlock() {        release(1);    }    public boolean isLocked() {        return isHeldExclusively();    }}
public static void main(String[] args) throws InterruptedException {    final SimpleLock lock = new SimpleLock();    lock.lock();    for (int i = 0; i < 10; i++) {        new Thread(new Runnable() {            @Override            public void run() {                lock.lock();                System.out.println(Thread.currentThread().getId() + " acquired the lock!");                lock.unlock();            }        }).start();        // 简单的让线程按照for循环的顺序阻塞在lock上        Thread.sleep(100);    }    System.out.println("main thread unlock!");    lock.unlock();}

运行上面的测试代码,结果如下:

main thread unlock!9 acquired the lock! 10 acquired the lock! 11 acquired the lock! 12 acquired the lock! 13 acquired the lock! 14 acquired the lock! 15 acquired the lock! 16 acquired the lock! 17 acquired the lock! 18 acquired the lock!

会发现等待的线程是按照阻塞时的顺序依次获取到锁的。 这是因为AQS是基于一个叫CLH lock queue的一个变种来实现线程阻塞队列的,我们下一篇文章就来简单了解下CLH lock queue。

后续文章计划如下:

  • 《Java并发包源码学习之AQS框架(二)CLH lock queue和自旋锁》
  • 《Java并发包源码学习之AQS框架(三)LockSupport》
  • 《Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析》
  • 《Java并发包源码学习之AQS框架(五)ConditionObject源码分析》

  ……

  • 《Java并发包源码学习之锁(一)概述》
  • 《Java并发包源码学习之锁(二)ReentrantLock源码分析》

  ……

  • 《Java并发包源码学习之线程池(一)概述》
  • 《Java并发包源码学习之线程池(二)ThreadPoolExecutor源码分析》

  ……

学习Java并发包源码的初衷是为了搞清之前遇到的,其实很早之前就打算看这块的源码但一直没看下去,所以说 看源码一定要有目的不能为了看而看。

 

转载于:https://www.cnblogs.com/zhanjindong/p/java-concurrent-package-aqs-overview.html

你可能感兴趣的文章
vue 发布网页
查看>>
【运维篇】如何使用SSB压测Apache Kylin
查看>>
Java反射实现不同对象相同代码地对象查询和封装
查看>>
前端开发应届生面试指南(含各大公司具体指南及面试真题)
查看>>
JAVA 多用户商城系统b2b2c-API网关服务(Spring Cloud Gateway)
查看>>
微博动漫打造“好故事计划”:良性商业循环让作者专注于创作
查看>>
【刘文彬】【精解】EOS TPS 多维实测
查看>>
JNI 基础 - Android 共享内存的序列化过程
查看>>
深入理解单例模式
查看>>
绚丽风车loading动效分析与实现!
查看>>
Mac 开发PHP 使用ThinkPHP
查看>>
理解D3中的数据连接(data join)和选取(selection)是怎么工作的
查看>>
centos7下Docker安装
查看>>
python学习笔记
查看>>
你们真的理解prototype和__proto__嘛?
查看>>
在 Windows Forms 和 WPF 应用中使用 FontAwesome 图标
查看>>
AWS开源Firecracker,一种运行多租户容器服务的新虚拟化技术
查看>>
为什么中台是传统企业数字化转型的关键?
查看>>
C# 7.1先睹为快(第二部分)
查看>>
命令: go build
查看>>