从零开始java多线程并发---锁(四):AQS原理简析

一:AQS原理简析

  AQS是java中多数的同步器的实现基础,AQS维护同步器的同步状态。在AQS中维护同步器状态,主要是从以下的三个方面来维护的:

  • 同步状态的管理
  • 线程的唤醒/阻赛
  • 线程等待队列的维护

二:同步状态的管理

  AQS同步器定义了资源的访问方式:独占模式还是共享模式。AQS使用单个32位的int来维护同步状态的,并且暴露出以下的方法来更新获取这个状态:

/**
 * 同步状态.
 */
private volatile int state;

protected final int getState() {
    return state;
}

protected final void setState(int newState) {
    state = newState;
}
/**
 * 以原子的方式更新同步状态.
 * 利用Unsafe类实现
 */
protected final boolean compareAndSetState(int expect, int update) {
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

其中一些同步器对于state的变量的使用:

                  

  

三:线程的唤醒和阻塞 

  我们知道在使用多线程时,常用的都是Object的wait(),notity()以及notityAll()来对线程进行阻塞和唤醒操作。在引入JUC这个并发包之后就有了LockSupport这个工具支持线程的操作,具体表现在锁的Condition中。

 

四:等待队列FIFO

  AQS的FIFO队列采用的是CLH队列(CLH队列),FIFO遵循一个基本的先进先出的原则。

1.FIFO存取线程的步骤

(1)首先,线程请求资源时先判断锁表示(state)是否上锁。如果没有上锁执行(2),否则执行(3)

(2)如果当前线程请求时没有上锁,使用原子操作,占用所标识。

(3)如果已经上锁,将当前线程相关信息封装成一个Node节点

(4)将该Node节点存放在队列尾部

(5)如果占锁的线程已经释放锁,那么通知队列的第一个Node节点释放并且占有锁。

 

2.FIFO中节点的API

       

static final class Node {
    
    // 共享模式结点
    static final Node SHARED = new Node();
    
    // 独占模式结点
    static final Node EXCLUSIVE = null;

    static final int CANCELLED =  1;

    static final int SIGNAL    = -1;

    static final int CONDITION = -2;

    static final int PROPAGATE = -3;

    /**
    * INITAL:      0 - 默认,新结点会处于这种状态。
    * CANCELLED:   1 - 取消,表示后续结点被中断或超时,需要移出队列;
    * SIGNAL:      -1- 发信号,表示后续结点被阻塞了;(当前结点在入队后、阻塞前,应确保将其prev结点类型改为SIGNAL,以便prev结点取消或释放时将当前结点唤醒。)
    * CONDITION:   -2- Condition专用,表示当前结点在Condition队列中,因为等待某个条件而被阻塞了;
    * PROPAGATE:   -3- 传播,适用于共享模式。(比如连续的读操作结点可以依次进入临界区,设为PROPAGATE有助于实现这种迭代操作。)
    * 
    * waitStatus表示的是后续结点状态,这是因为AQS中使用CLH队列实现线程的结构管理,而CLH结构正是用前一结点某一属性表示当前结点的状态,这样更容易实现取消和超时功能。
    */
    volatile int waitStatus;

    // 前驱指针
    volatile Node prev;

    // 后驱指针
    volatile Node next;

    // 结点所包装的线程
    volatile Thread thread;

    // Condition队列使用,存储condition队列中的后继节点
    Node nextWaiter;

    Node() {
    }

    Node(Thread thread, Node mode) { 
        this.nextWaiter = mode;
        this.thread = thread;
    }
}

 3.节点的指向

   Node节点的维护是用的一个双向链表,其中当前当前节点的状态一定是在前一个节点中某一个属性体现出了。这样就很容易实现Node节点的取消和删除功能(超时和响应中断的功能)

  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值