Java AQS unparkSuccessor 方法中for循环为什么是从tail开始而不是head

开映射定理与闭图象定理:Banach空间中的逆算子连续性与算子有界性 在泛函分析与现代数学物理中,Banach空间上的线性算子性质是理解无穷维结构的关键。有限维空间里双射线性映射的逆映射自动连续,但在无穷维空间中这一直觉不再成立。开映射定理指出,两个Banach空间之间的连续线性满射必然将开集映为开集,从而保证方程解的稳定性和逆算子的有界性;闭图象定理则提供了一条验证算子连续性的便捷路径,只要线性算子定义域是整个Banach空间且其图象闭合,即可断定该算子有界。这些定理在偏微分方程、数值分析和谱理论中具有广泛的应用,是构造稳定数值格式、分析算子谱性质以及证明空间同构关系的核心 阅读详情

1、前言

在AQS多线程竞争下的获取与释放流程中,我们提到过源码中唤醒节点的逻辑是从后尾部往前遍历找到最前的一个处于正常阻塞状态的结点

为什么从尾到头遍历?直接从头到尾的遍历形式有什么问题吗?今天我们就来通过源码的形式来理解一下,为什么要这样做。

2、尾部遍历源码

首先上源码:

private void unparkSuccessor(Node node) {
    //获取wait状态
    int ws = node.waitStatus;
    if (ws < 0)
        compareAndSetWaitStatus(node, ws, 0);// 将等待状态waitStatus设置为初始值0
    /**
     * 若后继结点为空,或状态为CANCEL(已失效),则从后尾部往前遍历找到最前的一个处于正常阻塞状态的结点
     * 进行唤醒
     */
    Node s = node.next;
    if (s == null || s.waitStatus > 0) {
        s = null;
        for (Node t = tail; t != null && t != node; t = t.prev)
            if (t.waitStatus <= 0)
                s = t;
    }
    if (s != null)
        LockSupport.unpark(s.thread);//唤醒线程
}

注意for循环中的逻辑:从尾部开始向前遍历,找到最前的一个处于正常阻塞状态的结点,直到节点重合(即等于当前节点)

3、高并发下入队逻辑

既然采用了从尾部遍历的逻辑,那么肯定是为了解决可能会出现的问题。而这个问题就在enq(…)方法中:

private Node enq(final Node node) {
    for (;;) {
        Node t = tail;
        if (t == null) { // Must initialize
            //队列为空需要初始化,创建空的头节点
            if (compareAndSetHead(new Node()))
                tail = head;
        } else {
            node.prev = t;
            //set尾部节点
            if (compareAndSetTail(t, node)) {//当前节点置为尾部
                t.next = node; //前驱节点的next指针指向当前节点
                return t;
            }
        }
    }
}


3.1 原子性问题

在该段方法中,将当前节点置于尾部使用了CAS来保证线程安全,但是请注意:在if语句块中的代码并没有使用任何手段来保证线程安全!

也就是说,在高并发情况下,可能会出现这种情况:

线程A通过CAS进入if语句块之后,发生上下文切换,此时线程B同样执行了该方法,并且执行完毕。然后线程C调用了unparkSuccessor方法。

假如是从头到尾的遍历形式,线程A的next指针此时还是null!也就是说,会出现后续节点被漏掉的情况。

3.2 图解流程

  1. 线程A执行CAS将当前节点置为尾部:在这里插入图片描述

  2. 原本线程A要执行t.next = node;将node2的next设置为node3,但是,此时发生上下文切换,时间片交由线程B,也就是说,此时node2的next还是null

  3. 线程B执行enq逻辑,最终CLH队列如图所示:在这里插入图片描述

  4. 此时发生上下文切换,时间片交由线程C,线程C调用了unparkSuccessor方法,假如是从头到尾的遍历形式,在node2就会发现,next指针为null,似乎没有后续节点了。

  5. 此时发生上下文切换,时间片交由线程A,A将node2的next=node3。奇怪的现象发生了:对于线程C来说,后续没有node3和node4,但是对于其它线程来说,却出现了这两个节点

4、结尾

从头部遍历会出现这种问题的原因我们找到了,最后我们再来说说为什么从尾部遍历不会出现这种问题呢?

其最根本的原因在于:
node.prev = t;先于CAS执行,也就是说,你在将当前节点置为尾部之前就已经把前驱节点赋值了,自然不会出现prev=null的情况

基于AQS驱动的ReentrantLock公平锁和非公平锁实现原理解析 本文通过代码调试分析了ReentrantLock的可重入特性及其底层AQS实现机制。重点解析了: 通过state变量记录锁重入次数,加锁时CAS递增,解锁时递减; 以NonfairSync为例展示了非公平锁的直接抢锁逻辑; 揭示了AQS通过volatile state变量和CAS操作实现同步状态管理; 完整跟踪了lock()/unlock()方法的执行流程,说明AQS是JUC锁工具的底层基础。 阅读详情

相关推荐

Java 并发锁体系全解:从 synchronized、Lock 到 AQS 底层原理与源码深度剖析

在 Java 并发编程体系中,锁是解决多线程共享资源竞争、保证线程安全的核心机制。从 JVM 内置的隐式锁,到 JUC 包提供的Lock显式锁,再到支撑整个并发工具集的底层基石 AbstractQueuedSynchronizer(AQS),构成了一套层层递进、设计精妙的锁实现体系。本文将从上层 API 到底层源码,完整拆解 Java 锁的核心原理,覆盖独占模式与共享模式、公平锁与非公平锁、条件队列与双队列联动、读写锁实现等核心知识点,结合 JDK 源码逐层剖析其设计思想与执行流程。

u013127325的博客 402

锁的释放流程-unparkSuccessor

private void unparkSuccessor(Node node) { int ws = node.waitStatus;//获得head节点的状态 if (ws < 0) compareAndSetWaitStatus(node, ws, 0);// 设置head节点 状态为0 Node s = node.next;//得到head节点的下一个节点 if (s == null || s.waitStatus > 0) { //如果下一个节点为null或者.

Leon_Jinhai_Sun的博客 1732

深入AQS:Java并发核心原理与自定义同步器实战

在Java并发编程中,锁和同步器是构建线程安全程序的基础组件。其核心原理在于通过原子操作和队列管理,协调多线程对共享资源的访问,以实现互斥与同步。AQS(AbstractQueuedSynchronizer)作为JUC(Java Util Concurrent)库的基石,采用模板方法模式,将复杂的线程排队、阻塞与唤醒机制封装成通用框架,其价值在于为开发者提供了构建高性能、可扩展同步器(如ReentrantLock、Semaphore)的底层支撑。在高并发场景下,理解AQS的state状态管理、CLH队列变体

weixin_34413103的博客 426

AQS详解

AQS简介 在同步组件的实现中,AQS是核心部分,同步组件的实现者通过使用AQS提供的模板方法实现同步组件语义。 AQS 则实现了对同步状态的管理,以及对阻塞线程进行排队,等待通知等等一些底层的实现处理。 AQS的核心也包括了这些方面:同步队列,独占式锁的获取和释放,共享锁的获取和释放以及可中断锁,超时等待锁获取这些特性的实现,而这些实际上则是AQS提供出来的模板方法。 同步队列 当共享资源被...

sifanchao的博客 2万+

浅谈Java的AQS

所谓AQS,指的是AbstractQueuedSynchronizer,它提供了一种实现阻塞锁和一系列依赖FIFO等待队列的同步器的框架,ReentrantLock、Semaphore、CountDownLatch、CyclicBarrier等并发类均是基于AQS来实现的,具体用法是通过继承AQS实现其模板方法,然后将子类作为同步组件的内部类。 了解一个框架最好的方式是读源码,说干就干。 AQS是...

打酱油的葫芦娃 7899

从ReentrantLock理解AQS的原理及应用总结

本文介绍了Java中的AbstractQueuedSynchronizer(AQS),重点讲解了其在实现ReentrantLock等同步器中的应用。文章分析了AQS的基本概念、工作原理及关键数据结构,并探讨了其在多线程竞争中的线程排队与唤醒机制。通过对AQS实现的深入剖析,帮助开发者更好地理解并发编程中的锁机制和自定义同步器的实现。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 171万+

第10讲:深入理解 AQS 和 CAS 原理

深入理解 AQS 和 CAS 原理

ChinaDragon10的博客 1319

STK相关总结

STK简介 一.SIM卡应用工具包(SIM Application Toolkit),又名CAT/USAT,它包含一系列终端与SIM卡的交互指令,SIM卡可以应用卡内的小应用程序和终端交互,从而实现增值服务的目的,STK包括三种类,STK-imsi切换,STK –OTA,STK-BIP 功能: (1) Profile download:配置下载,开机初始化SIM卡过程中,终端告诉SIM卡终端支持哪些功能,STK中download指终端将数据发送给SIM卡 (2) Proactive command: 主动式

jingjing_2的博客 3356

java tail head_Java AQS unparkSuccessor 方法中for循环从tail开始而不是head的疑问?

用 API 的实现来证明自己的观点, 逻辑上是不正确的. 因为 AQS 的核心是一个 CLH 队列的变体, 整个 API 都依赖它实现. 所以是先有的 Node 类, 然后才有基于它实现的 API.在 AQS 的 wait queue 中, 每个结点 status 都保存在它的前驱结点中 ( predecessor ). 那么为什么要这么设计? 用每个结点保存自己的 status, 然后只有当该结...

weixin_39678525的博客 360

爬取国家统计局最近10年年度数据

一、编码流程 1.目标网址:https://data.stats.gov.cn/easyquery.htm?cn=C01 2.编码思路: (1) 解析左侧指标树,实现4级标签定位 (难点:层层嵌套,下一级指标的xpath路径以上一级指标为基础;不是所有二级指标都含有三和四级指标,需要进行判断) (2) 使用selenium webdriver 点选指标,加载出右侧表格数据 (难点:当指标无法在全局页面显示时,需向下拖动滚动条) (3) 解析右侧数据,实现数据存储 3.使用模块: (1) selenium:解

weixin_39645690的博客 4556

微生物组数据分析实战:从OTU/ASV过滤到相对丰度转换的标准化流程

本文详细介绍了微生物组数据分析中从原始OTU/ASV表格到标准化相对丰度表格的完整预处理流程。通过基于绝对丰度和出现频率的过滤步骤有效剔除测序噪音与污染,再通过相对丰度转换解决样本间测序深度差异问题,为后续的多样性分析和差异比较奠定可靠基础。文章提供了清晰的R语言实战代码与参数设置思路。

tree的博客 1253

【大白话说Java面试题 第111题】【并发篇】第11题:谈谈你对 AQS 的理解?

本文深入解析了Java并发编程中的核心框架AQS(AbstractQueuedSynchronizer),它是ReentrantLock等同步器的底层实现基础。AQS采用状态(state)+队列(同步队列与条件队列)+CAS的架构,通过模板方法模式将具体锁逻辑交由子类实现。重点分析了Node节点的waitStatus状态机(5种状态流转)及其在CLH变体队列中的作用,包括独占/共享模式下的线程阻塞与唤醒机制。文章通过结构示意图和代码示例,揭示了AQS如何通过无锁CAS与阻塞park的混合策略实现高效线程同步

Java后端 | AI智能体应用实战派 | 电脑技能行家 790

IPsec (主模式,野蛮模式)

IPsec vpn的主模式和野蛮模式

七汣的博客 3414

java进阶-7-D -多线程-Lock专题- AQS源码剖析

AQS-AbstractQueuedSynchronizer 介绍 1.开篇第一件事情,就是先将 Node 这个内部静态类搞清楚了 Node{ SHARED Node 共享锁的标志 (默认值 new Node()) EXCLUSIVE Node 独占锁标志 (默认 为 null) CANCELLED int 1 该节点的线程已经...

qq_33199919的博客 214

DDR5内存调优实战:手把手教你搞定Write Leveling Training Mode(附时序图解析)

本文深入解析DDR5内存调优中的Write Leveling Training Mode技术,详细介绍了其核心原理、硬件准备、实战步骤及常见问题解决方案。通过JESD79-5标准定义的反馈机制,帮助硬件工程师精确对齐DQS与CK信号,提升系统稳定性和数据可靠性。附有时序图解析和代码示例,适合DDR5内存系统设计与调试参考。

weixin_29256771的博客 549

网规第三版:第4章网络资源设备(完结)

第 4 章 网络资源设备 调整内容: 更新主流网络设备(交换机、路由器、防火墙)的技术参数与选型标准 增加国产化网络设备与信创产品的相关内容 精简已淘汰的设备类型与技术指标

鹿鸣天涯 266

深入拆解AQS的CLH同步队列:从入队到唤醒的完整并发机制

并发编程中,锁与同步器的底层实现往往被视为“玄学”。AQS(AbstractQueuedSynchronizer)作为Java并发包的核心框架,其CLH同步队列的设计决定了ReentrantLock、Semaphore等工具的公平性与性能。理解队列如何通过CAS自旋入队、如何借助volatile state与LockSupport实现线程阻塞与唤醒,是掌握并发原理的关键。从工程实践看,无论是实现自定义同步工具,还是优化线程池的阻塞队列选择,都离不开对AQS队列模型的深刻认知。本文基于JDK 8源码,完整拆解

weixin_33883104的博客 207

【JTAG】1500协议详解

随着集成电路的规模不断扩大,1149.1的板级测试无法满足要求越来越高的芯片测试需求。芯片规模变大后,测试需求不在是一次测试整片芯片,而是芯片分为好几个区域去测试,而1500协议正是对1149.1在该方面的一个补充即1149.1主要测试板级间的互连,而1500用来测试芯片内不同core之间的互连。IEEEStd1500已经为包含不同模块的集成电路(ICs)开发了一种可测试性设计标准方法。............

xuhe0206的博客 7018

Java AQS 原理与同步器实战

本文深入解析了Java并发包中的核心同步器AQS及其典型实现CountDownLatch和CyclicBarrier。AQS采用CLH队列和state状态管理机制,通过模板方法模式支持独占和共享两种同步模式。CountDownLatch基于AQS共享模式实现一次性计数功能,适用于主线程等待多个子任务完成的场景;CyclicBarrier则基于可重入锁实现多线程相互等待的屏障,具备循环使用的特性。两者都适用于并行任务协调,但CountDownLatch不可重置而CyclicBarrier可循环使用。文章通过U

RonieWhite的博客 241

SAP FAGLFLEXT 是 SAP 新总账的核心余额表,存储多维度的汇总余额数据。核心结论:该表按 “科目 + 会计年度 + 期间 + 维度” 存储累计余额,字段可分为基础标识

FAGLFLEXT是SAP新总账的核心余额表,采用"科目+年度+期间+维度"结构存储多维汇总数据。其字段分为基础标识(科目、年度等)、维度细分(公司代码、利润中心等15个维度)、金额数值(本外币余额)、辅助控制(状态标识)四大类,支持新总账的灵活核算。该表通过凭证自动更新,与旧总账GLT0相比显著扩展了维度核算能力,各维度需在科目主数据或Ledger配置中启用才能使用。

金牌架构师 454

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

java队列加锁_[Java并发] AQS抽象队列同步器源码解析--独占锁释放过程

上一篇已经讲解了AQS独占锁的获取过程,接下来就是对AQS独占锁的释放过程进行详细的分析说明,废话不多说,直接进入正文...锁释放入口release(int arg)首先进行说明下,能够正常执行到release方法这里来的线程都是获取到锁的,从下面代码可以看出释放锁步骤只有两个重要的方法:tryRelease与unparkSuccessor ,tryRelease尝试释放锁,unparkSucce...

weixin_31062007的博客 187

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

【大白话说Java面试题 第112题】【并发篇】第12题:AQS 中节点的入队时机有哪些?

摘要: AQS(AbstractQueuedSynchronizer)的节点入队时机分为同步队列和条件队列两类: 同步队列: 独占锁(acquire)、共享锁(acquireShared)获取失败时,通过addWaiter尾插法入队,含快速路径(CAS设尾)和慢速路径(自旋初始化队列)。 可中断/超时锁获取(如acquireInterruptibly)失败时,逻辑类似但支持中断响应。 条件队列: 调用Condition.await()时,线程释放锁并加入条件队列(单线程操作,无需CAS),同时清理已取消节点

Java后端 | AI智能体应用实战派 | 电脑技能行家 312

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

深度学习工具包 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")

07-JUC并发基础-AQS

同步状态(state)

Bonnie_1215的博客 161

AQS源码解析(一)

今天笔者带大家深入刨析AQS源码的每个方法!!! 方法一: protected final boolean compareAndSetState(int expect, int update) { return unsafe.compareAndSwapInt(this, stateOffset, expect, update); } 方法解读:如果当前状态值等于预期值,则自动将同步状态设置为给定的更新值。此操作具有volatile读写的内存语义。 参数值:参数expec..

Mr_Police的博客 531
上一篇: nginx反向代理导致后端session失效解决方案
下一篇: 聊聊SPI机制以及为什么说SPI破坏了双亲委派模型
评论 26
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值