并发编程AQS(网课整理)(未完)

AQS

1、AQS的产生背景

通过JCP的JSR166规范,Jdk1.5开始引入了j.u.c包,这个包提供了一系列支持并发的组件。这些组件是一系列的同步器,这些同步器主要维护着以下几个功能:内部同步状态的管理(例如表示一个锁的状态是获取还是释放),同步状态的更新和检查操作,且至少有一个方法会导致调用线程在同步状态被获取时阻塞,以及在其他线程改变这个同步状态时解除线程的阻塞。上述的这些的实际例子包括:互斥排它锁的不同形式、读写锁、信号量、屏障、Future、事件指示器以及传送队列等。可以看下这里图便能理解 j.u.c包的组件构成。
在这里插入图片描述
几乎任一同步器都可以用来实现其他形式的同步器。例如,可以用可重入锁实现信号量或者用信号 量实现可重入锁。但是,这样做带来的复杂性、开销及不灵活使j.u.c最多只能是一个二流工程,且缺乏吸引力。如果任何这样的构造方式不能在本质上比其他形式更简洁,那么开发者就不应该随意地选择其中的某个来构建另一个同步器。因此,JSR166基于AQS类建立了一个小框架,这个框架为构造同步器提供一种通用的机制,并且被j.u.c包中大部分类使用,同时很多用户也可以用它来定义自己的同步器。这个就是j.u.c的作者Doug Lea大神的初衷,通过提供AQS这个基础组件来构建j.u.c的各种工具类,至此就可以理解AQS的产生背景了。

2、AQS的设计和结构

2.1 设计思想

同步器的核心方法是acquire和release操作,其背后的思想也比较简洁明确。

  • acquire操作是这样的:
    while (当前同步器的状态不允许获取操作) { 
    	如果当前线程不在队列中,则将其插入队列
    	阻塞当前线程 
    }
    如果线程位于队列中,则将其移出队列
    
  • release操作是这样的:
    更新同步器的状态
    if (新的状态允许某个被阻塞的线程获取成功)
    	解除队列中一个或多个线程的阻塞状态
    

从这两个操作中的思想中我们可以提取出三大关键操作:同步器的状态变更、线程阻塞和释放、插入和移出队列。所以为了实现这两个操作,需要协调三大关键操作引申出来的三个基本组件:

  • 同步器状态的原子性管理;
  • 线程阻塞与解除阻塞;
  • 队列的管理;

由这三个基本组件,我们来看j.u.c是怎么设计的。

2.1.1 同步状态

AQS类使用单个int(32位)来保存同步状态,并暴露出getState、setState以及compareAndSet 操作来读取和更新这个同步状态。其中属性state被声明为volatile,并且通过使用CAS指令来实现 compareAndSetState,使得当且仅当同步状态拥有一个一致的期望值的时候,才会被原子地设置成新 值,这样就达到了同步状态的原子性管理,确保了同步状态的原子性、可见性和有序性。

基于AQS的具体实现类(如锁、信号量等)必须根据暴露出的状态相关的方法定义tryAcquire和 tryRelease方法,以控制acquire和release操作。当同步状态满足时,tryAcquire方法必须返回true, 而当新的同步状态允许后续acquire时,tryRelease方法也必须返回true。这些方法都接受一个int类型的参数用于传递想要的状态。

2.1.2 阻塞

。。。。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值