AbstractQueuedSynchronizer怎么用的?

AbstractQueuedSynchronizer是一个很复杂的抽象类,主要用于实现线程同步的各类解决方案,一共两千多行代码,本文不分析源码细节,试图从宏观层面分析AbstractQueuedSynchronizer的设计思路以及一些实际的使用场景。

1、在线程的6种状态中,有三种使线程暂停的状态:BLOCKED/WAITING/TIME_WAITING,AQS将处于这三种状态的线程封装到Node这样一个数据结构中,BLOCKED状态的线程组成一个Node双端队列,WAITING/TIME_WAITING状态的线程组成1个或多个Node单向队列。用一个volatile int state字段代表竞争的共享资源,提供独占/共享两种抢占共享资源的方式,*acquire/releaseShared代表共享方式的API。类中最下面一排列出了最常用的几个类,他们都是基于AQS实现的,像大家常用的ReentrantLock类,就是一种独占竞争资源的解决方案。

 

2、ReentrantLock,基于AQS实现的独占式可重入锁。

a. lock()方法实际上调用了AQS的acquire(1),所以很多AQS的源码分析都是以acquire()方法作为入口分析的;

b. 可重入,是指同一个线程在未释放已获取的竞争资源时继续获取竞争资源,对于AQS,就是state++,获取多次就需要释放多次,才能完整的释放持有的竞争资源。

c. 支持公平/非公平方式,区别就是非公平方式忽略AQS中的Node双端队列的优先级顺序,每次获取锁会忽略排队直接尝试抢占共享资源。

 

3、Semaphore/CountDownLatch,基于AQS实现的共享式线程同步解决方案。

a. Semaphore对外包装成acquire()/release()方法,实际使用的AQS的共享式竞争的机制,Semaphore一般用于控制并发量,即初始化时设置并发数,然后多个线程共享抢占这些并发数,如果并发数是1,就相当于独占锁。

b. CountDownLatch对外包装成await()/countDown()方法,也是使用AQS的共享式竞争的机制,初始化时设置的共享值会直接赋值给state,每调用一次countDown()方法,state--,直到state=0,所有await方法被唤醒或直接返回执行。

 

 

4、ReentrantReadWriteLock,基于AQS实现的独占/共享式混合的线程同步解决方案。区分读写线程,写线程独占资源,读线程共享资源,即读-读不冲突,读-写/写-写是冲突的。

a. state字段同时记录独占/共享两种方式的资源竞争状态,高16位代表共享资源使用数,低16位单表独占资源使用数,使用位移及位与操作进行计算。

b. 支持写锁降级为读锁(apparentlyFirstQueuedisExclusive()),即一个线程持有写锁的同时可以获取到读锁,反之不行。

 

以上对AQS的使用场景做了一些基本介绍,以前都是直接使用RenentrantLock这些类,但不知道是基于大名鼎鼎的AQS类实现的。在了解了AQS的设计思路和现有的一些实现类之后,如果有必要的话,也可以自己实现与业务场景对应的线程同步解决方案,比如下图中tomcat中就有用到AQS实现LimitLatch。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值