8、AQS

AQS(抽象队列同步器)

1、AQS解决了什么问题

CAS自旋实现的轻量级锁的两大问题

  1. CAS空自旋浪费大量CPU资源
  2. 导致“总线风暴”(大量的cas操作导致总线流量剧增)

关于总线风暴以及总线锁的知识,参考http://t.csdn.cn/3wLCD

解决CAS恶性空自旋有效方式(空间换时间)两种方式

  1. 分散热点,类似LongerAdder、ConcurrentHashMap
  2. 队列削峰(JUC通过AQS实现)

2、学习AQS之前,了解一下CLH锁(作为AQS的雏形)

请添加图片描述

CLH锁的特点:

  • 单向FIFO队列(公平锁)
  • 竞争资源在一个时间点只能被一个线程锁访问(即队列的头部,表示占用锁的节点)
  • 新加入的抢锁线程需要等待,通过CAS插入队列尾部

3、AQS的内部队列

请添加图片描述

AQS的特点:

  • 双向FIFO队列
    • 每个Node封装了线程,分别指向前驱节点和后继节点
3.1 Node节点(静态内部类)
 static final class Node {
   
      	//表示线程是因为获取共享资源时阻塞,而被添加到队列中的
        static final Node SHARED = new Node();
    	// 表示线程因为获取独占资源时阻塞,而被添加到队列中的。
        static final Node EXCLUSIVE = null;
		//以下是节点的状态
     	//取消状态 1
        static final int CANCELLED =  1;
		//节点等待状态 -1:标识后继线程处于等待状态
        static final int SIGNAL    = -1;
		//节点等待状态 -2:标识当前线程处于条件等待      
        static final int CONDITION = -2;
		//节点等待状态 -3:标识下一次共享锁的acquireShared操作需要无条件传播     
        static final int PROPAGATE = -3;
     	
     	//节点状态:Canceled Signal Condition Propagate 0
     	//普通同步节点的初始值为0,条件等待节点的初始值为-2
        volatile int waitStatus;
		//前驱节点,当前节点会在前驱节点上自选,检查前驱节点的waitStatus的状态
        volatile Node prev;

        volatile Node next;

        volatile Thread thread;
		//如果当前Node不是普通节点,而是条件等待节点,则节点处与某个条件的等待队列上
     	//此属性指向下一个条件等待节点
        Node nextWaiter;

waitStatus属性:

  1. Canceled:标识该线程节点已释放(超时、中断),已取消的节点不会被阻塞,需要从等待队列中取消等待
  2. Signal:表示其后继节点处于等待状态,如果当前节点被取消或释放,会通知其后继节点
  3. Condition:
  4. Propagate:waitStatus为-3时,表示该下个线程获取共享锁,自己的共享状态会被无条件的传播下去,因为共享锁可能出现同时有N个锁可以用
3.2 AQS的核心成员
//队头节点	
private transient volatile Node head;
//队尾节点
private transient volatile Node tail;
//标记为状态,AQS适用state标识锁的状态  
private volatile int state;
//设置同步状态(无法保证原子性)
protected final void setState(int newState) {
   
        state = newState;
    }
//通过同步状态(通过CAS保证原子性)    
protected final boolean compareAndSetState(int expect, int update) {
   
        // See below for intrinsics setup to support this
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }
关于ReentrantLock可重入特性

​ ReentrantLock初始化state为0,表示未锁定状态。线程A调用tryAcquire()独占该锁并使其state+1.其他线程对该锁tryAcquire()会失败。直到A线程unlock该锁的state为0(释放锁)。A线程在此过程中,可以重复获取该锁(state累加),累加多少次,就要释放多少次。

3.3 AbstractOwnableSynchronizer(查看占用该锁(独占锁的情形下生效)的线程)

AQS继承了AbstractOwnableSynchronizer

请添加图片描述

public abstract class AbstractOwnableSynchronizer
    implements java.io.Serializable {
   

    /** Use serial ID even though all fields transient. */
    private static final long serialVersionUID = 3737899427754241961L;

    /**
     * Empty constructor for use by subclasses.
     */
    protected AbstractOwnableSynchronizer() {
    }

    /**
     * The current owner of exclusive mode synchronization.
     独占锁情形下,占用该锁的线程
     */
    private tra
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值