AQS源码阅读

ROS 2在自动驾驶中的应用:感知节点开发 ROS 2在自动驾驶中的应用:感知节点开发 ,人工智能,计算机视觉,大模型,AI,本文围绕ROS 2在自动驾驶感知节点开发展开,介绍了ROS 2基础、感知节点开发流程,包括环境搭建、代码编写等,还阐述了常用传感器感知节点开发、多传感器融合,以及测试调试、性能优化、部署集成等内容,分析了开发面临的挑战与未来趋势,为相关开发提供了全面指导,涉及简单代码示例和概念解释。 阅读详情

简介

AQS 全程为
AbstractQueuedSynchronizer , 在 java.util.concurrent.locks包下的一个抽象类。

类的具体作用以及设计在开始类描述信息里面就有很好的表达

Provides a framework for implementing blocking locks and related
synchronizers (semaphores, events, etc) that rely on
first-in-first-out (FIFO) wait queues.  This class is designed to
be a useful basis for most kinds of synchronizers that rely on a
single atomic {@code int} value to represent state. Subclasses
must define the protected methods that change this state, and which
define what that state means in terms of this object being acquired
or released.  Given these, the other methods in this class carry
out all queuing and blocking mechanics. Subclasses can maintain
other state fields, but only the atomically updated {@code int}
value manipulated using methods {@link #getState}, {@link
#setState} and {@link #compareAndSetState} is tracked with respect
to synchronization.	
具体翻译为:
提供了实现阻塞锁和相关的框架,依赖于的同步器(信号量、事件等)。
先进先出 (FIFO) 等待队列。 这个类被设计为对于大多数依赖于单个原子 {@code int} 值来表示状态。 
子类必须定义更改此状态的受保护方法,以及根据正在获取的对象定义该状态的含义或释放。 鉴于这些,此类中的其他方法带有排除所有排队和阻塞机制。 子类可以维护其他状态字段,但只有原子更新的 {@code int}使用方法 {@link #getState}、{@link 操作的值#setState} 和 {@link #compareAndSetState} 被地跟踪、同步。

简单描述为:通过原子性的int值来标记同步状态,实现阻塞锁机制,基于FIFO队列来实现排队机制

AQS实现了两种模式,独占模式和共享模式,实现共享锁和排他锁

以独占锁为例,FIFO队列头节点获取到锁之后,其他节点会进入等待状态,释放锁之后,头节点的下一个节点会尝试获取锁,但是不一定成功(公平、非公平)。

LockSupport工具类

LockSupport 官方是这样描述的 Basic thread blocking primitives for creating locks and other , 翻译为 “基本线程阻塞原语,用于创建锁和其他”,可以理解为使用计算机原语来创建锁,底层实现为unsafe类,主要方法为pack(线程阻塞)与unpack(唤醒线程),源码如下:

// LockSupport设置阻塞分为两组,
	// 一组是不设置blocker的方法,另一组是设置blocker方法
	// JDK推荐为Thread设置blocker方便调试
	public static void park(Object blocker) {
        // 获取当前线程
        Thread t = Thread.currentThread();
        // blocker位线程内存当前偏移量,设置线程内存偏移量,
        setBlocker(t, blocker);
        // Unsafe包下的方法可以直接操作内存,设置线程阻塞
        U.park(false, 0L);
        // 线程唤醒后 blockers设置为空
        setBlocker(t, null);
    }
    public static void park() {
        // 线程阻塞,单纯唤醒,不会记录偏移量
        U.park(false, 0L);
    }
	// 与park基本相同,添加阻塞事件,自动唤醒
	public static void parkNanos(Object blocker, long nanos);
	public static void parkUntil(Object blocker, long deadline);
// unpark方法为unsafe.unpark方法,为C++实现,基于内存进行操作
	public static void unpark(Thread thread) {
        if (thread != null)
            U.unpark(thread);
    }

 

AQS内部结构

AQS类图

 

AQS的实现类为NofairSync(非公平)、FairSync(公平)两种。

内部类Node

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;
      // 节点在等待队列中,节点线程等待在Condition上,当其他线程对Condition调用了signal()后,该节点将会从等待队列中转移到同步队列中,加入到同步状态的获取中
      static final int CONDITION = -2;
      // 表示下一次共享式同步状态获取将会无条件地传播下去
      static final int PROPAGATE = -3;
      // 等待状态
      volatile int waitStatus;
      // 前驱结点
      volatile Node prev;
      // 后继节点
      volatile Node next;
      // Node封装当前线程
      volatile Thread thread;
      // 指向ConditionObject的下一个节点
      Node nextWaiter; 
    }

节点状态

  1. CANCELLED (1):当前线程因为超时或者中断被取消。这是一个终结态,也就是状态到此为止
  2. SIGNAL (-1):当前线程的后继线程被阻塞或者即将被阻塞,当前线程释放锁或者取消后需要唤醒后继线程。这个状态一般都是后继线程来设置前驱节点的
  3. CONDITION (-2):当前线程在condition队列中
  4. PROPAGATE (-3):用于将唤醒后继线程传递下去,这个状态的引入是为了完善和增强共享锁的唤醒机制。在一个节点成为头节点之前,是不会跃迁为此状态的

主要属性

/**
 * 等待队列的头节点, 赖加载
 * 除了初始化之外, 只能通过 setHead 方法来改变其值
 * 如果 head 不为 null, waitStatus 值就一定不会是 CANCELLED
 */
private transient volatile Node head;
 
/**
 * 等待队列的尾结点, 懒加载
 * 只能通过 enq 方法添加新节点时才会去改变尾结点
 */
private transient volatile Node tail;
 
/**
 * 同步器的状态
 * 以 ReentrantLock 为例, 0 表示可以获取到锁, 其他的正整数表示无法获取到锁
 */
private volatile int state;

AQS属性结构设计如下

 

具体方法

开放实现接口API,用于场景自定义:

方法

作用

boolean tryAcquire(int arg)

试获取独占锁

boolean tryRelease(int arg)

试释放独占锁

int tryAcquireShared(int arg)

试获取共享锁

boolean tryReleaseShared(int arg)

试释放共享锁

boolean isHeldExclusively()

当前线程是否获得了独占锁

AQS本身将同步状态的管理用模板方法模式都封装好了,以下列举了AQS中的一些模板方法

方法

描述

void acquire(int arg)

获取独占锁。会调用 tryAcquire 方法,如果未获取成功,则会进入同步队列等待

void acquireInterruptibly(int arg)

响应中断版本的 acquire

boolean tryAcquireNanos(int arg,long nanos)

响应中断+带超时版本的 acquire

void acquireShared(int arg)

获取共享锁。会调用 tryAcquireShared 方法

void acquireSharedInterruptibly(int arg)

响应中断版本的 acquireShared

boolean tryAcquireSharedNanos(int arg,long nanos)

响应中断+带超时版本的 acquireShared

boolean release(int arg)

释放独占锁

boolean releaseShared(int arg)

释放共享锁

Collection getQueuedThreads()

获取同步队列上的线程集合

源码层面上会对acquire、release、acquireShared 、releaseShared 进行详解

独占锁

 

// 获取独占锁  	
public final void acquire(int arg) {
        if (!tryAcquire(arg) && // 试获取独占锁,获取同步状态 
            // addWaiter,将线程封装成Node节点,添加到同步队列的尾部,acquireQueued,自旋等待,如果获取状态失败,挂起线程
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) 
            selfInterrupt(); // 线程中断
}

private Node addWaiter(Node mode) {
    //创建Node节点
    Node node = new Node(mode);

    for (;;) {
        // 当前队尾进行标记
        Node oldTail = tail;
        if (oldTail != null) {
            node.setPrevRelaxed(oldTail);
            // CAS操作放到队尾
            if (compareAndSetTail(oldTail, node)) {
                oldTail.next = node;
                return node;
            }
        } else {
            initializeSyncQueue();
        }
    }
}
// 将该线程加入等待队列的尾部,并标记为独占模式
final boolean acquireQueued(final Node node, int arg) {
    boolean interrupted = false;
    try {
        // 自旋,不断尝试当前线程获取锁,知道成功或者线程被打断
        for (;;) {
            // 获取前驱节点
            final Node p = node.predecessor();
            // 尝试获取锁
            if (p == head && tryAcquire(arg)) {
                // 成功之后将节点设置为新的头部节点
                setHead(node);
                p.next = null; // help GC
                return interrupted;
            }
            // 获取锁失败
            // 判断线程是否需要中断, 判断标准是前节点状态
            if (shouldParkAfterFailedAcquire(p, node))
                //挂起当前线程
                interrupted |= parkAndCheckInterrupt();
        }
    } catch (Throwable t) {
        cancelAcquire(node);
        if (interrupted)
            selfInterrupt();
        throw t;
    }
}
// 如果线程获取同步状态失败就要检查它的节点status,要保证prev = node.prev
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
    // 前驱节点状态
    int ws = pred.waitStatus;
    // singal 表示前驱节点释放后会唤起当前线程,会继续等待,那么线程可以中断等待
    if (ws == Node.SIGNAL)
        return true;
    // 前驱节点不是Head节点,并且状态为CANCELLED,那么就需要剔除前置节点,向前遍历,直到找到合适的前置
    if (ws > 0) {
        do {
            node.prev = pred = pred.prev;
        } while (pred.waitStatus > 0);
        pred.next = node;
    } else {
        // 这种情况表示前驱节点的 ws = 0 或者 ws = PROPAGATE,那么设置前驱节点为singal,之后重新循环获取锁
        pred.compareAndSetWaitStatus(ws, Node.SIGNAL);
    }
    return false;
}

acquire方法为获取独占锁

  1. tryAcquire() 尝试直接去获取资源,如果成功则直接返回true,AQS中空方法,由实现类来实现,具体分析会在ReentrantLock中进行详细代码分析。
  2. addWaiter() 将该线程加入等待队列的尾部,并标记为独占模式
  3. acquireQueued()使线程阻塞在等待队列中获取资源,一直获取到资源后才返回。如果在整个等待过程中被中断过,则返回true,否则返回false。如果线程在等待过程中被中断过,它是不响应的。只是获取资源后才再进行自我中断selfInterrupt(),将中断补上
    // 独占锁释放节点
    public final boolean release(int arg) {
        // tryRelease由实现类具体实现
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                // 唤醒下一个节点
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

release方法通过tryRelease()实现了扩展性,来进行锁的重入设计,unparkSuccessor则自身实现,完成了下一个Node节点的唤醒

共享锁

public final void acquireShared(int arg) {
    // tryAcquireShared为抽象方法,由子类实现
    if (tryAcquireShared(arg) < 0)
        doAcquireShared(arg);
}	

private void doAcquireShared(int arg) {
    // 不断尝试从队列中获取共享锁,当成功获取到锁或者线程被打断时会成功退出循环,竞争锁失败的线程会被 park 直到被唤醒,唤醒之后会再次进入循环尝试去获取锁,不断的重复整个过程
    final Node node = addWaiter(Node.SHARED);
    boolean interrupted = false;
    try {
        for (;;) {
            final Node p = node.predecessor();
            if (p == head) {
                int r = tryAcquireShared(arg);
                if (r >= 0) {
                    setHeadAndPropagate(node, r);
                    p.next = null; // help GC
                    return;
                }
            }
            // 上面由详细解读
            if (shouldParkAfterFailedAcquire(p, node))
                interrupted |= parkAndCheckInterrupt();
        }
    } catch (Throwable t) {
        cancelAcquire(node);
        throw t;
    } finally {
        if (interrupted)
            selfInterrupt();
    }
}

// 释放共享锁
public final boolean releaseShared(int arg) {
    // 子类实现
    if (tryReleaseShared(arg)) {
        
        doReleaseShared();
        return true;
    }
    return false;
}
//当前节点调用
private void doReleaseShared() {
    for (;;) {
        Node h = head;
        if (h != null && h != tail) {
            int ws = h.waitStatus;
            // 如果头节点状态为SIGNAL, 表示可以去释放锁
            if (ws == Node.SIGNAL) {
                // 通过 cas 将 waitStatus 设为 0
                if (!h.compareAndSetWaitStatus(Node.SIGNAL, 0))
                    continue;            // loop to recheck cases
                // 线程唤醒
                unparkSuccessor(h);
            }
            else if (ws == 0 &&
                     !h.compareAndSetWaitStatus(0, Node.PROPAGATE))
                continue;                // loop on failed CAS
        }
        if (h == head)                   // loop if head changed
            break;
    }
}

 

关于独占锁和共享锁的异同

相同

1)获取锁前都会判断是否有权限,只有满足条件才可能获取到锁

2)未获取到锁的线程会创建新节点放入队列尾部

不同

1)独占锁只会释放头部后节点的线程,而共享锁会依次释放所有线程

2)独占锁存在非公平锁的情况,新的线程可能抢占队列中线程的锁,共享锁则不存在这种情况

扩展

AQS使用了模板方法的设计模式,以固定的方法进行调用,子类对其实现,方便扩展,后续会对具体实现类继续读源码。

Microsemi Libero系列教程(四)——PLL的使用 文章目录PLL是什么Libero中PLL的使用官方文档 系列教程:Microsemi Libero系列教程 PLL是什么 PLL(Phase Locked Loop): 为锁相回路或锁相环,用来统一整合时钟信号,使高频器件正常工作,如内存的存取资料等。PLL用于振荡器中的反馈技术。 许多电子设备要正常工作,通常需要外部的输入信号与内部的振荡信号同步。一般的晶振由于工艺与成本原因,做不到很高的频率... 阅读详情

相关推荐

PyQt5 + HFSS:给你的仿真脚本做个专属GUI界面(零基础搭建指南)

本文详细介绍了如何使用PyQt5为HFSS仿真脚本创建专属GUI界面,适合零基础用户快速上手。通过Python二次开发,实现参数可视化调整、进度实时监控等功能,大幅提升团队协作效率。文章涵盖环境配置、界面设计、HFSS集成到打包部署的全流程,是仿真工程师提升工作效率的实用指南。

weixin_42535720的博客 186

AbstractQueuedSynchronizer(AQS)源码分析

AbstractQueuedSynchronizer(AQS)源码分析

ZHENHAOYOUNI的博客 237

HarmonyOS ArkTS开发实战:用Axios封装一个通用的网络请求工具类(附完整代码)

本文详细介绍了如何在HarmonyOS ArkTS开发中利用Axios封装一个通用的网络请求工具类,涵盖架构设计、核心模块实现、UI状态联动及高级功能扩展。通过单例控制器、拦截器链配置和Token自动刷新机制,提升网络请求的稳定性和可维护性,适用于各类HarmonyOS应用开发场景。

weixin_30772105的博客 491

AQS的源码解析(自己的理解)

AQS的源码解析(自己的理解) 一:AQS的前置知识 AQS涉及到以下知识点:如不清楚可以去B站上看尚硅谷的大厂面试第二季juc 1.juc 2.LockSupper 3.模板模式 4.CAS 二:AQS是什么 字面意思: Abstract Queued Synchronizer(抽象的队列同步器) 实现原理: status成员变量+CLH队列变种 FIFO双向虚拟队列 简单流程理解: 通过控制stauts变量来表示锁的状态,0代表资源开发 1代表目前有人占用资源 默认初始化0,抢不到线程的资

weixin_43861634的博客 5306

DDR5内存ODT模式全解析:5种状态与实战配置指南(附时序图)

本文深入解析DDR5内存的片上终端电阻(ODT)机制,详细阐述了其五种核心状态(终结电阻禁用、RTT_WR、RTT_NOM_RD、RTT_NOM_WR、RTT_PARK)的定义、切换时序与工作原理。通过解读JESD79-5规范中的时序图,并提供基于模式寄存器的实战配置指南与代码示例,帮助硬件工程师和系统开发者优化信号完整性,解决高负载下的稳定性问题,并实现性能与功耗的最佳平衡。

weixin_29221753的博客 566

保姆级教程:用xmir-patcher一键解锁Redmi AX3000路由器的SSH(附视频演示)

本文提供Redmi AX3000路由器SSH解锁的保姆级教程,详细介绍了使用xmir-patcher工具一键解锁SSH的步骤,包括环境搭建、工具获取、图形化操作详解及常见问题排查。解锁后,用户可通过SSH连接实现刷机、插件安装、网络优化等高级功能,提升路由器性能。

weixin_29216049的博客 738

AQS学习与源码阅读

AQS全称抽象队列同步器,是一个用来构建锁和同步器的框架。可以用来构造应用广泛的同步器,比如SemaphoreFutureTask。

qq_45678095的博客 748

S7-1200控制S120变频器

②:硬件目录下,添加实物S120设备进行组态(其它现场设备--PROFINET IO--DRIVES......②:双击S120进行IP地址和设备名称设置(注:此处要与STATER软件设置S120一致)M10.0接通时,电机开始运行,M10.0断开,电机停止,调试完成。①:将S7-1200与S120进行通讯连线。④:STATER软件下设置与组态一致的报文。①:点击添加新设备,按实物进行设备组态。②:打开OB1,编写启动停止程序。①:查看S120报文地址。②:模块下添加DO矢量。③:子模块下添加报文。

weixin_38261173的博客 4868

AQS源码阅读(JDK1.8)

一、简介 AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它,是Java中众多锁以及并发工具的基础,其底层采用乐观锁,大量使用了CAS操作, 并且在冲突时,采用自旋方式重试,以实现轻量级和高效地获取锁。 AQS虽然被定义为抽象类,但事实上它并不包含任何抽象方法。这是因为AQS是被设计来支持多种用途的,如果定义抽象方法,则子类在继承时必须要覆写所有的抽象方法,这显然是不合理的。所以AQS将一些需要子类覆写的方法都设计成protect方法,将其默认实现为抛出UnsupportedOpera

小望没烦恼的博客 549

Python 爬虫实战:爬取电商平台商品信息(价格 / 销量 / 评价)

摘要:本文详细介绍基于Python的电商商品信息爬取技术方案,以京东商品详情页为例,对比分析静态(BeautifulSoup)和动态(Selenium)两种爬取方式的实现逻辑。静态爬取适合获取基础信息,而动态爬取可解决JS渲染数据的获取问题。文章包含完整的代码实现、反爬规避策略及数据存储方案,涵盖商品名称、价格、销量、评价等核心数据提取。同时强调爬虫的合规使用,提供扩展方向建议,为电商数据采集提供实用技术参考。

2503_91057718的博客 2025

【数据集6】全球人工不透水面积GAIA(清华数据)

全球人工不透水面GAIA简介及其应用

WW、forever的博客 3808

AQS源码阅读感想

1.AQS核心原理 --AQS拥有变量state,通过CAS设定state得值是否成功判断是否获得锁,源码如下: compareAndSetState(c, nextc) protected final boolean compareAndSetState(int expect, int update) { return unsafe.compareAndSwapInt(thi...

idealemail的博客 172

Autosar诊断实战系列07-Dcm之0x19 06扩展数据配置及工程问题讨论

19 06扩展数据如何配置?如果某DTC没有出现过故障扩展数据该如何响应?

initiallizer的博客 1705

深入AQS源码阅读与强软弱虚4种引用以及ThreadLocal原理与源码

写在片头:声明,勿杠 首先简单说一下,这三次面试阿里并不是一次性去面的,实际上第一次面试时候还在大四,找的实习岗,不太清楚是什么部门,别问我为什么还记得面试题,有记录和复盘的习惯,再问就是杠。 个人背景不详细多说,学历双非本科,不是应届生,工作年限不长,技术不是大牛,但也非小白,面经分享是想给正面试的同行一些建议和鼓励,希望能够多多支持。 注意:下文内容中会提到一些简历模板、学习笔记、学习脑图、Java电子书籍和视频等,需要的私信我口令【成长】免费领取。 One:三顾茅庐,七面阿里,..

m0_63437643的博客 515

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

JAVA劝退系列AQS源码阅读

这里写自定义目录标题新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图 新的改变 我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客: 全新的界面设计 ,将会带来全新的写

烟花易冷 260

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

AQS源码阅读笔记(上)

场景信号传播机制关键缺陷结果理想状态顺序执行无竞争无工作正常无 PROPAGATE依赖单一状态检查并发释放导致信号丢失T2 永远阻塞有 PROPAGATE双重保障:1. PROPAGATE 标记2. 强制传播检查解决信号丢失所有线程正确唤醒。

agentoflyra的博客 1424

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

AQS源码阅读记录

AQS定义两种资源共享方式:Exclusive(独占,只有一个线程能执行,如ReentrantLock)和Share(共享,多个线程可同时执行,如Semaphore/CountDownLatch)使用acquire/release(模板)方法对外提供功能。使用一个双向队列和指向队列两端的head/tail指针来实现线程的有序排队, ps:head指针指向的第一个node为傀儡node,不包含真实...

qq_37720278的博客 210

AQS源码阅读与理解

什么是AQS Provides a framework for implementing blocking locks and related synchronizers (semaphores, events, etc) that rely on first-in-first-out (FIFO) wait queues. This class is designed to be a useful basis for most kinds of synchronizers that rely on a

weixin_43180484的博客 262

AQS源码分析以及基于AQS之上的各种实现,带你阅读源码

AQS本质是一个双向队列,线程被包装成了一个个节点,节点在队列里面通过自旋一直尝试获取资源 AQS有两个队列 一个同步队列,一个条件队列 其实我感觉这个队列框架 和重量级锁的框架很像 有entrylist 代表着正在等待资源的线程队列,是双向的,entrylist叫等待队列,然后当获得资源的线程,使用了wait以后就进入了waitset,这里面的等待线程,就要等待一定条件后,然后被唤醒,再去entrylist的头部或者尾部进行争夺资源。waitset又叫条件等待队列,条件满足了,就被唤醒去等待队列。 这些

qq_45602114的博客 273

aqs,源码阅读,图解

AQS 是一个抽象类,提供了很多同步相关的默认实现,如线程入队、资源获取和释放等,子类可以继承 AQS 并通过重写一些关键方法来实现特定的同步器(如等)。Sync是内部类,用于具体实现不同同步器的业务逻辑,负责对锁的获取和释放等操作的实现。状态字段和 CAS:AQS 使用state字段表示同步状态,通过 CAS 操作来保证对共享资源状态的安全修改。等待队列:AQS 使用双向链表来管理等待队列,确保线程按照公平的顺序竞争资源。

qq_41577703的博客 177

从ReentrantLock到AQS源码阅读

ReentrantLock是使用AQS实现的一种可重入的独占锁,并且提供了公平和非公平两种策略。 ReentractLock的内部类Sync继承了AbstractQueuedSynchronizer抽象类,并且提供了两个内部类FairSync和NonfairSync(即公平锁与非公平锁的落地实现),而具体采用哪一种加锁策略则则是由ReentractLock的构造函数进行指定。 public ReentrantLock() { sync = new NonfairSync(); } public R

Nicholas_GUB的博客 702

阅读AQS -- AbstractQueuedSynchronizer源码

什么是AQS? 具体的类位于 : java.util.concurrent.locks.AbstractQueuedSynchronizer AQS是基于FIFO等待队列的,用来实现阻塞锁和相关同步机制的框架, 比如信号量(semaphroe), 事件(events), 可重入读写锁之类的,都是用这个实现的。其内部是使用原子int来表示状态的。子类需要覆盖其中的protected方法来实现同步机制。 AQS同时支持排他模式和共享模式。排他模式情况下,如果一个线程已经有锁了,其他线程是无法获取到锁的。共享模式

sparrowxin的博客 216
上一篇: Spring5源码-事务的创建、回滚、提交
下一篇: 硬核!阿里自爆虐心万字面试手册,Github上获赞89.7K
java_lujj
博客等级 码龄4年 18粉丝 152原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值