AQS相关

本文详细介绍了AQS(AbstractQueuedSynchronizer)的概念及其作为阻塞锁和同步器框架的作用,并深入探讨了ReentrantLock的具体实现,包括公平与非公平锁的区别,以及与AQS之间的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近一直在学习asq底层部分,现在将其做一些整理如下;

AQS是什么?

其实aqs 就是AbstractQueuedSynchronizer 的简称

同时查看AbstractQueuedSynchronizer 源码的注释部分

Provides a framework for implementing blocking locks and related
synchronizers (semaphores, events, etc) that rely on
first-in-first-out (FIFO) wait queues. 

大致意思:提供一个框架来实现阻塞锁和相关的依赖于的同步器(信号量、事件等)先进先出(FIFO)等待队列。
我们也可以看到AbstractQueuedSynchronizer 是抽象类,那么我对它的理解就是能够帮助我们实现阻塞和同步器框架;

其ReentrantLock就是比较明显的实现类,其实java.concurrent.util包而juc当中的大多数同步器实现都是围绕AQS进行的,其都有着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等

ReentrantLock

ReentrantLock是一种基于AQS框架的应用实现,是JDK中的一种线程并发访问的同步 手段,它的功能类似于synchronized是一种互斥锁,可以保证线程安全。而且它具有比 synchronized更多的特性,比如它支持

  • 阻塞等待队列

  • 共享/独占

  • 公平/非公平

  • 可重入

  • 允许中断

其实ReentrantLock并不是直接继承AQS来进行保持同步的,它内部有着一个内部类Sync,而这个Sync,对于Juc下面,比如 CountDownLatch Semaphore的实现也是有的

ReentrantLock实现公平与非公平性
在ReentrantLock内部定义了一个Sync的内部类,该类继承AbstractQueuedSynchronized,对 该抽象类的部分方法做了实现;并且还定义了两个子类:
1、FairSync 公平锁的实现
2、NonfairSync 非公平锁的实现 这两个类都继承自Sync,也就是间接继承了AbstractQueuedSynchronized,所以这一个 ReentrantLock同时具备公平与非公平特性。

AQS 的重要属性

// 头结点,你直接把它当做 当前持有锁的线程 可能是最好理解的
private transient volatile Node head;

// 阻塞的尾节点,每个新的节点进来,都插入到最后,也就形成了一个链表
private transient volatile Node tail;

// 这个是最重要的,代表当前锁的状态,0代表没有被占用,大于 0 代表有线程持有当前锁
// 这个值可以大于 1,是因为锁可以重入,每次重入都加上 1
private volatile int state;

// 代表当前持有独占锁的线程,举个最重要的使用例子,因为锁可以重入
// reentrantLock.lock()可以嵌套调用多次,所以每次用这个来判断当前线程是否已经拥有了锁
// if (currentThread == getExclusiveOwnerThread()) {state++}
private transient Thread exclusiveOwnerThread; //继承自AbstractOwnableSynchronizer



static final class Node {
    // 标识节点当前在共享模式下
    static final Node SHARED = new Node();
    // 标识节点当前在独占模式下 Semaphore会用到
    static final Node EXCLUSIVE = null;

    // ======== 下面的几个int常量是给waitStatus用的 ===========
    /** waitStatus value to indicate thread has cancelled */
    // 代码此线程取消了争抢这个锁
    static final int CANCELLED =  1;
    /** waitStatus value to indicate successor's thread needs unparking */
    // 官方的描述是,其表示当前node的后继节点对应的线程需要被唤醒
    static final int SIGNAL    = -1;
    /** waitStatus value to indicate thread is waiting on condition */
    // 条件等待
    static final int CONDITION = -2;
    /**
     * waitStatus value to indicate the next acquireShared should
     * unconditionally propagate
     */
    // 广播
    static final int PROPAGATE = -3;
    // =====================================================


 	// 标记当前节点的信号量状态 (1,0,‐1,‐2,‐3)5种状态
    // 使用CAS更改状态,volatile保证线程可见性,高并发场景下
    // 即被一个线程修改后,状态会立马让其他线程可见。
    volatile int waitStatus;
    // 前驱节点的引用
    volatile Node prev;
    // 后继节点的引用
    volatile Node next;
    // 节点同步状态的线程
    volatile Thread thread;
    //也就是说节点类型(独占和共享)和等待队列中的后继节点共用同一个字段。
	 Node nextWaiter;
}

同步等待队列/条件等待队列

同步等待队列

CLH队列 基于双向链表数据结构的队列 是FIFO先入先出线程等待队列,Java中的CLH 队列是原CLH队列的一个变种,线程由原自旋机制改为阻塞机制。
在这里插入图片描述

条件等待队列

Condition是一个多线程间协调通信的工具类,使得某个,或者某些线程一起等待某个条件(Condition),只有当该条件具备时,这些等待线程才会被唤醒,从而重新争夺锁

在这里插入图片描述

	//公平锁的分析
	private static ReentrantLock lock = new ReentrantLock(true);
	lock.lock(); 

我画的导图
https://www.processon.com/view/link/60501e64637689019dde2f0e

lock()/ lockInterruptibly()

lockInterruptibly()// 如果线程阻塞 是被中断了,不会获得锁,会产生异常
lock(); //获得锁定,即使调用了线程的interrupt()方法,也没有真正的中断线程

为什么lockInterruptibly不会获取锁,返回异常?
查看源码得知:
在这里插入图片描述

BlockingQueue

查看官方文档可以知道其为线程通信的一个工具,在任意时刻,单jvm同一时间只有一个线程可以进行take或者put操作

DelayQueue

那么它下面有一个实现类DelayQueue,通过名字可以知道它是延迟的队列,同时看了它的源码可知其通过PriorityQueue来实现,也用到了ReentrantLock;
当然我在在建立放对象的队列时发现需要放入实现Delayed接口(Delayed实现了Comparable接口)的对象;需要实现一个getDelay的方法;

	Delayed接口
    /**
     * Returns the remaining delay associated with this object, in the
     * given time unit.
     *
     * @param unit the time unit
     * @return the remaining delay; zero or negative values indicate
     * that the delay has already elapsed
     */
    long getDelay(TimeUnit unit);
    
    Comparable接口
        /**
     * Compares this object with the specified object for order.  Returns a
     * negative integer, zero, or a positive integer as this object is less
     * than, equal to, or greater than the specified object.
     *
     * <p>The implementor must ensure <tt>sgn(x.compareTo(y)) ==
     * -sgn(y.compareTo(x))</tt> for all <tt>x</tt> and <tt>y</tt>.  (This
     * implies that <tt>x.compareTo(y)</tt> must throw an exception iff
     * <tt>y.compareTo(x)</tt> throws an exception.)
     *
     * <p>The implementor must also ensure that the relation is transitive:
     * <tt>(x.compareTo(y)&gt;0 &amp;&amp; y.compareTo(z)&gt;0)</tt> implies
     * <tt>x.compareTo(z)&gt;0</tt>.
     *
     * <p>Finally, the implementor must ensure that <tt>x.compareTo(y)==0</tt>
     * implies that <tt>sgn(x.compareTo(z)) == sgn(y.compareTo(z))</tt>, for
     * all <tt>z</tt>.
     *
     * <p>It is strongly recommended, but <i>not</i> strictly required that
     * <tt>(x.compareTo(y)==0) == (x.equals(y))</tt>.  Generally speaking, any
     * class that implements the <tt>Comparable</tt> interface and violates
     * this condition should clearly indicate this fact.  The recommended
     * language is "Note: this class has a natural ordering that is
     * inconsistent with equals."
     *
     * <p>In the foregoing description, the notation
     * <tt>sgn(</tt><i>expression</i><tt>)</tt> designates the mathematical
     * <i>signum</i> function, which is defined to return one of <tt>-1</tt>,
     * <tt>0</tt>, or <tt>1</tt> according to whether the value of
     * <i>expression</i> is negative, zero or positive.
     *
     * @param   o the object to be compared.
     * @return  a negative integer, zero, or a positive integer as this object
     *          is less than, equal to, or greater than the specified object.
     *
     * @throws NullPointerException if the specified object is null
     * @throws ClassCastException if the specified object's type prevents it
     *         from being compared to this object.
     */
    public int compareTo(T o);

从我使用我理解到的意思是返回倒计时时间
从下面的源码可以看出

在这里插入图片描述
而DelayQueue先按照Comparable接口对所有元素进行排序,一般情况下,我们都是按元素过期时间的优先级进行排序。这里,即按照倒计时时间短进行排序;

eg:

public class Mian2 {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<DelayedElement > delayeds = new DelayQueue<DelayedElement >();
        String strDateFormat = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
        System.out.println(sdf.format(System.currentTimeMillis()));
        DelayedElement element1 = new DelayedElement(5000);
        delayeds.offer(element1);
        DelayedElement element2 = new DelayedElement(10000);
        delayeds.offer(element2);
        DelayedElement element3 = new DelayedElement(15000);
        delayeds.offer(element3);
        DelayedElement element4 = new DelayedElement(20000);
        delayeds.offer(element4);
        new Thread(()-> {
                while (true){
                    DelayedElement elementt = null;
                    try {
                        elementt =  delayeds.take();
                        System.out.println(sdf.format(System.currentTimeMillis())+elementt);

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
        }).start();



    }
}
class DelayedElement implements Delayed{

    private long delay ;
    private final long expire;


    public DelayedElement (long delay) {
        this.expire = System.currentTimeMillis() + delay;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }

    @Override
    public int compareTo(Delayed o) {
        return (int) (this.getDelay(TimeUnit.MILLISECONDS) -o.getDelay(TimeUnit.MILLISECONDS));
    }
}


内容概要:本文针对国内加密货币市场预测研究较少的现状,采用BP神经网络构建了CCi30指数预测模型。研究选取2018年3月1日至2019年3月26日共391天的数据作为样本,通过“试凑法”确定最优隐结点数目,建立三层BP神经网络模型对CCi30指数收盘价进行预测。论文详细介绍了数据预处理、模型构建、训练及评估过程,包括数据归一化、特征工程、模型架构设计(如输入层、隐藏层、输出层)、模型编译与训练、模型评估(如RMSE、MAE计算)以及结果可视化。研究表明,该模型在短期内能较准确地预测指数变化趋势。此外,文章还讨论了隐层节点数的优化方法及其对预测性能的影响,并提出了若干改进建议,如引入更多技术指标、优化模型架构、尝试其他时序模型等。 适合人群:对加密货币市场预测感兴趣的研究人员、投资者及具备一定编程基础的数据分析师。 使用场景及目标:①为加密货币市场投资者提供一种新的预测工具和方法;②帮助研究人员理解BP神经网络在时间序列预测中的应用;③为后续研究提供改进方向,如数据增强、模型优化、特征工程等。 其他说明:尽管该模型在短期内表现出良好的预测性能,但仍存在一定局限性,如样本量较小、未考虑外部因素影响等。因此,在实际应用中需谨慎对待模型预测结果,并结合其他分析工具共同决策。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值