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

文章目录

  • AQS
    • 1、AQS的产生背景
    • 2、AQS的设计和结构
      • 2.1 设计思想
        • 2.1.1 同步状态
        • 2.1.2 阻塞

AQS

1、AQS的产生背景

通过JCP的JSR166规范,Jdk1.5开始引入了j.u.c包,这个包提供了一系列支持并发的组件。这些组件是一系列的同步器,这些同步器主要维护着以下几个功能:内部同步状态的管理(例如表示一个锁的状态是获取还是释放),同步状态的更新和检查操作,且至少有一个方法会导致调用线程在同步状态被获取时阻塞,以及在其他线程改变这个同步状态时解除线程的阻塞。上述的这些的实际例子包括:互斥排它锁的不同形式、读写锁、信号量、屏障、Future、事件指示器以及传送队列等。可以看下这里图便能理解 j.u.c包的组件构成。
并发编程AQS(网课整理)(未完)_第1张图片
几乎任一同步器都可以用来实现其他形式的同步器。例如,可以用可重入锁实现信号量或者用信号 量实现可重入锁。但是,这样做带来的复杂性、开销及不灵活使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 阻塞

。。。。。。

你可能感兴趣的:(java,java,并发)