当前位置:   article > 正文

什么是AQS?AQS有什么作用?常见的基于AQS的组件有哪些?

aqs

1.什么是AQS

AQS队列同步器(AbstractQueuedSynchronizer),是用来构建锁或者其他同步组件的基础框架。
它使用了一个int的成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作。
同步器的主要使用方式是继承,子类通过基础同步器并实现它的抽象方法来管理同步状态,在抽象方法的实现过程中免不了对同步状态进行更改,这时需要使用同步器提供的三个方法(getState()、setState(int newState)和compareAndSetState(int expect,int update)来操作,因为他们能够保证状态的改变是安全的。

2.AQS的原理

AQS队列同步器是如何完成线程同步的?
主要包括:同步队列、独占式同步状态获取与释放、共享式同步状态获取与释放以及超时获取同步状态等同步器的核心数据结构与模板方法。

2.1同步队列

同步器依赖内部的同步队列(一个FIFO)双向队列完成状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态等信息构造成一个节点(Node)并将其加入同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点中的线程唤醒,使其再次获取同步状态。
在这里插入图片描述
同步器包含了两个节点类型的引用,一个指向头节点,而另一个指向尾节点。
如果一个线程成功获取了同步状态,其他线程无法获取到同步状态,转而被构造成节点并加入同步队列中,而加入队列的过程必须要保证线程安全,因此同步器提供了一个基于CAS设置尾节点的方法:compareAndSetTail(Node expect,Node update),它需要传递当前线程认为的尾节点和当前节点,只有设置成功后,当前节点才正式与之前的尾节点建立关联。
在这里插入图片描述
同步队列遵循FIFO,首节点是获取同步状态成功的节点,首节点的线程在释放同步状态时,将会唤醒后继节点,而后继节点将会在获取同步状态将会在获取同步状态成功时将自己设置为首节点。该过程见5-3。
因为设首节点是通过获取同步状态完成的线程来完成的,由于只有一个线程能够获取到同步状态,因此设置头节点的方法并不需要CAS来保证。只需要将首节点设置为原首节点的后继节点并断开原首节点的next引用即可。
在这里插入图片描述

2.2独占式同步状态的获取与释放

通过调用同步器的acquire(int arg)方法可以获取同步状态,该方法对中断不敏感,也就是由于线程同步状态失败后进入同步队列中,后续对线程进行中断操作时,线程不会从同步队列中移出。
  • 1
public final void acquire(int arg){
   
	if(!tryAcquire(arg)&&acquireQueued(addWaited(Node.EXCLUSIVE),arg){
   
		selfInterrupt();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

上述代码主要完成了同步状态获取、节点构造、加入同步队列以及在同步队列中自旋等待的相关工作,其主要逻辑是:首先调用自定义同步器实现tryAcquire(int arg)方法,该方法保证线程安全的获取同步状态,如果同步状态获取失败,则构造同步节点(独占式Node.EXCLUSIVE,同一时刻只能有一个线程成功获取同步状态)并通过addWaiter(Node node)方法将该节点加入到同步队列的尾部,最后调用acquireQueued(Node node,int arg)方法,使得该节点以死循环的方式获取同步状态,如果获取不到则阻塞节点中的线程,而被阻塞线程的唤醒主要依靠前驱节点的出队或阻塞线程被中断来实现。

//同步器的addWaiter和enq方法
private Node addWaiter(Node node){
   
	Node node = new Node(Thread.currentThread(),node);
	//快速尝试在尾部添加
	Node pred = tail;
	if(pred!=null){
   
		node.prev = pred;
		if(compareAndSetTail(pred,node){
   
			pred.next = node;
			return node;
		}
	}
	enq(node);
	return node;
}
private Node enq(
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/149031
推荐阅读
相关标签
  

闽ICP备14008679号