加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_丽江站长网 (http://www.0888zz.com/)- 科技、建站、数据工具、云上网络、机器学习!
当前位置: 首页 > 站长资讯 > 动态 > 正文

深挖AQS队列同步器

发布时间:2021-04-19 09:27:23 所属栏目:动态 来源:互联网
导读:级实现的,juc包下的Lock显示锁,而提到Lock就不得不提一下它的核心队列同步器(AQS)了,它的全称是AbstractQueuedSynchronizer,是用来构建锁或者其他一些同步组件的基础,除了ReentrantLock、ReentrantReadWriteLock外,它还在CountDownLatch、Semaphore以

级实现的,juc包下的Lock显示锁,而提到Lock就不得不提一下它的核心队列同步器(AQS)了,它的全称是AbstractQueuedSynchronizer,是用来构建锁或者其他一些同步组件的基础,除了ReentrantLock、ReentrantReadWriteLock外,它还在CountDownLatch、Semaphore以及ThreadPoolExecutor中被使用,通过理解队列同步器的工作原理,对我们了解和使用这些工具类会有很大的帮助。

1、AQS 基础

为了便于理解AQS的概念,这里首先摘录部分AbstractQueuedSynchronizer的注释进行了简要翻译:

  • 它提供了一个框架,对于依赖先进先出等待队列的阻塞锁和同步器(例如信号量和事件),可以用它来实现。这个类的设计,对于大多数依赖于单个原子值来表示状态(state)的同步器,可以提供有力的基础。子类需要重写被protected修饰的方法,例如更改状态(state),定义在获取或释放对象时这些状态表示的含义。基于这些,类中的其他方法实现了队列和阻塞机制。在子类中可以维护其他的状态字段,但是只有使用getState,setState,compareAndSetState方法原子更新的状态值变量,才与同步有关。
  • 子类被推荐定义为非public的内部类,用来实现封闭类的属性同步。同步器本身没有实现任何同步接口,它仅仅定义了一些方法,供具体的锁和同步组件中的public方法调用。
  • 队列同步器支持独占模式和共享模式,当一个线程在独占模式下获取时,其他线程不能获取成功,在共享模式下多线程的获取可能成功。在不同模式下,等待的线程使用的是相同的先进先出队列。通常,实现子类只支持其中的一种模式,但是在ReadWriteLock中两者都可以发挥作用。只支持一种模式的子类在实现时不需要重写另一种模式中的方法。

阅读这些注释,可以知道AbstractQueuedSynchronizer是一个抽象类,它基于内部先进先出(FIFO)的双向队列、以及内置的一些protected方法来实现同步器,完成同步状态的管理,并且我们可以通过子类继承AQS抽象类的方式,在共享模式或独占模式下,实现自定义的同步组件。

通过上面的描述,可以看出AQS中的两大核心是同步状态和双向的同步队列,来看一下源码中是如何对它们进行定义的:这两个核心内容分别进行研究。

同步队列

AQS内部静态类Node用于表示同步队列中的节点,变量表示的意义如下:

  • prev:当前节点的前驱节点,如果当前节点是同步队列的头节点,那么prev为null
  • next:当前节点的后继节点,如果当前节点是同步队列的尾节点,那么next为null
  • thread:获取同步状态的线程
  • waitStatus:等待状态,取值可为以下情况
  1. CANCELLED(1):表示当前节点对应的线程被取消,当线程等待超时或被中断时会被修改为此状态
  2. SIGNAL(-1):当前节点的后继节点的线程被阻塞,当前线程在释放同步状态或取消时,需要唤醒后继节点的线程
  3. CONDITION(-2):节点处于等待队列中,节点线程等待在Condition上,当其他线程调用Condition的signal方法后,会将节点从等待队列移到同步队列
  4. PROPAGATE(-3):表示下一次共享式同步状态获取能够被执行,即同步状态的获取可以向后继节点的后继进行无条件的传播
  5. 0:初始值,表示当前节点等待获取同步状态

每个节点的prev和next指针在加入队列的时候进行赋值,通过这些指针就形成了一个双向列表,另外AQS还保存了同步队列的头节点head和尾节点tail,通

(编辑:应用网_丽江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读