AQS是什么?Java并发编程大师的源码不得不拜读呀

头歌平台 操作系统课堂练习2.3:系统调用 使用 gdb 调试内核,跟踪到 main 函数入口的方法与之前实训一样。系统运行时,执行的前 3 个系统调用的编号和名字分别是什么?系统运行时,执行的前 3 个系统调用的编号和名字分别是什么?本关卡使用版本 1 内核进行分析,版本 1 内核文件存放在。为了完成本关任务,你需要:跟踪系统调用的发生。此时,系统调用号存放在寄存器 eax 中。 阅读详情

目录

初识ReentrantLock

什么是AQS

AQS中的同步状态state

CLH变体队列

独占模式

共享模式

公平锁&非公平锁

结语


大家好,我是tin,这是我的第13篇原创文章

​

文章首发于公众号【看点代码再上班】,欢迎围观,第一时间获取最新文章。

今天把ReentrantLock和AQS一起翻一翻,通过源码说一说我们的Java锁。

初识ReentrantLock

首先,我们同时启用5个线程对一个公共变量counter从0开始累加,每个线程只对变量+1,理想的情况是公共变量最后值等于5,类似如下结果:

thread(0) @【看点代码再上班】, thread state:RUNNABLE
thread(1) @【看点代码再上班】, thread state:WAITING
thread(2) @【看点代码再上班】, thread state:WAITING
thread(3) @【看点代码再上班】, thread state:WAITING
thread(4) @【看点代码再上班】, thread state:WAITING
counter:2
thread(0) @【看点代码再上班】, thread state:TERMINATED
thread(1) @【看点代码再上班】, thread state:RUNNABLE
thread(2) @【看点代码再上班】, thread state:WAITING
thread(3) @【看点代码再上班】, thread state:WAITING
thread(4) @【看点代码再上班】, thread state:WAITING
counter:3
thread(0) @【看点代码再上班】, thread state:TERMINATED
thread(1) @【看点代码再上班】, thread state:TERMINATED
thread(2) @【看点代码再上班】, thread state:WAITING
thread(3) @【看点代码再上班】, thread state:RUNNABLE
thread(4) @【看点代码再上班】, thread state:WAITING
counter:4
thread(0) @【看点代码再上班】, thread state:TERMINATED
thread(1) @【看点代码再上班】, thread state:TERMINATED
thread(2) @【看点代码再上班】, thread state:RUNNABLE
thread(3) @【看点代码再上班】, thread state:TERMINATED
thread(4) @【看点代码再上班】, thread state:WAITING
counter:5
thread(0) @【看点代码再上班】, thread state:TERMINATED
thread(1) @【看点代码再上班】, thread state:TERMINATED
thread(2) @【看点代码再上班】, thread state:TERMINATED
thread(3) @【看点代码再上班】, thread state:TERMINATED
thread(4) @【看点代码再上班】, thread state:RUNNABLE
复制代码

我把线程的状态一起打印出来了,从图而知,对counter的累加是线程安全的,每次只有一个线程处于RUNNABLE状态,其他的线程要么处于WAITING,要么处于TERMINATED状态。

我把测试代码也截图发出来: 

​ps:如要测试源码,可到此下载:github.com/iam-tin/tin…

我们对ReentrantLock的初步认识大多是从lock()和unlock()方法开始的,我们用得比较多的也是此两方法(除此之外还有tryLock()等方法)。

当我们调用lock()方法的时候,ReentrantLock是如何实现共享变量单线程锁定的呢?当调用unlock()方法的时候,ReentrantLock又是如何把锁释放而通知其他WAITING的线程去获取锁的呢?

以上问题就涉及到了我们Java中大名鼎鼎的AQS了。通过源码可以看到ReentrantLock#lock()实际是调用的抽象内部类Sync的lock()方法,FairSync(公平锁)和NonfairSync(非公平锁)分别继承了Sync类:

​顺藤摸瓜,找到Sync类其实是继承AbstractQueuedSynchronizer(AQS), 

​不管是FairSync还是NonFairSync,底层都是用AQS的能力实现。

什么是AQS

说到Java中的并发编程,一定绕不开AQS(AbstractQueuedSynchronizer),它是我们伟大的Java作者Doug Lea(我特喜欢这个老爷子)的又一大杰作!

看看官方文档是怎么描述AQS的:

​AQS又称抽象队列同步器,是并发包(java.util.concurrent)的基础框架,很多我们熟悉的锁和同步组件都是依赖于AQS,比如ReentrantLock、ReentrantReadWriteLock、CountDownLatch、Semaphore。AQS底层则依靠CAS(竞争锁)与同步队列,如下图: 

​

AQS中的同步状态state

不同线程要获取锁,AQS实际上是通过一个volatile变量来控制的,这个变量就是state,表示同步状态。和state相关的方法主要有三个方法getState(),setState(),compareAndSetState()

/**
     * The synchronization state.
     */
    private volatile int state;
​
    /**
     * Returns the current value of synchronization state.
     * This operation has memory semantics of a {@code volatile} read.
     * @return current state value
     */
    protected final int getState() {
        return state;
    }
​
    /**
     * Sets the value of synchronization state.
     * This operation has memory semantics of a {@code volatile} write.
     * @param newState the new state value
     */
    protected final void setState(int newState) {
        state = newState;
    }
​
    /**
     * Atomically sets synchronization state to the given updated
     * value if the current state value equals the expected value.
     * This operation has memory semantics of a {@code volatile} read
     * and write.
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that the actual
     *         value was not equal to the expected value.
     */
    protected final boolean compareAndSetState(int expect, int update) {
        // See below for intrinsics setup to support this
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }
复制代码

很明显,线程可以通过compareAndSetState方法(实际是CAS)获取锁,compareAndSetState被调用的地方有哪些呢?见下图: 

​compareAndSetState(0, 1)可以理解为线程尝试首次获取锁,compareAndSetState(c, c + acquires)可以理解为多次获取同一把锁。

CLH变体队列

CLH是一个双向链表队列,其关键数据结构为:Node。Node即为CLH变体队列中的节点,它把线程封装起来,一个节点可以理解为一个要准备竞争锁的线程。

static final class Node {
        //共享模式节点标记
        static final Node SHARED = new Node();
        //独占模式节点标记
        static final Node EXCLUSIVE = null;
        /** waitStatus value to indicate thread has cancelled */
        static final int CANCELLED =  1;
        /** waitStatus value to indicate successor's thread needs unparking */
        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;
        //上面四种状态值,初始值为0
        volatile int waitStatus;
        //前驱指针
        volatile Node prev;
        //后继指针
        volatile Node next;
        //和节点绑定的线程
        volatile Thread thread;
        //等待条件的下一个节点
        Node nextWaiter;
}
复制代码

独占模式

独占模式表示同一时间只能有一个线程占有同一把锁(和重入不一样,重入表示同一个线程可以多次获取锁),ReentrantLock就是一个独占锁(同时它也是可重入的)。我们看看独占模式获取锁的逻辑acquire()方法:

    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
复制代码

tryAcquire(arg)尝试获取锁,如果获取不到则把当前线程包装为一个独占模式的节点放到队列的末尾,然后acquireQueued方法把线程挂起阻塞,直到获取锁。 

​(acquire()对应锁释放方法是release(int arg)。)

共享模式

共享模式表示同一把锁可以被多个线程同时拥有。我们经常看到的ReadWriteLock、CountdownLatch、Semaphere都是共享模式。

和独占模式acquire()方法相对应,我们看下共享模式下acquireShared(int arg)方法是如何获取锁的。

public final void acquireShared(int arg) {
        if (tryAcquireShared(arg) < 0)
            doAcquireShared(arg);
    }
复制代码

tryAcquireShared(arg)只是AQS定义的一个模板,具体实现都在各种锁的实现类下,tryAcquireShared(arg)返回值只要大于等于0都认为是获取锁成功。我们简单看下信号量Semaphore的tryAcquireShared实现是怎么样的: 

​Semaphore同样分为公平锁和非公平锁,默认下是非公平锁。Semaphore比较简单,它只认信号量剩余量,只要没有超出都可以获取锁,所以也就是同一时间同一个共享资源可以多线程共享的(信号量大于1的情况下)。 

​读写锁ReadWriteLock相对复杂一些,因为分为了读锁和写锁,但我们只要记住读锁是共享模式、写锁是独占模式、对于同一把锁的CLH队列不同节点既可以是共享模式也可以是独占模式,这样读写锁也就非常好理解了。 

​

​

再回到获取共享锁最开始的方法上:

public final void acquireShared(int arg) {
        if (tryAcquireShared(arg) < 0)
            doAcquireShared(arg);
    }
复制代码

如果tryAcquireShared(arg) < 0,就会执行doAcquireShared(arg),这个方法主要逻辑是把线程包装为一个共享模式的节点Node放到同步队列的末端直至获取到锁。但是和独占模式不同的是,doAcquireShared如果获取到锁会马上通知后继节点去获取锁。 

​

公平锁&非公平锁

公平与非公平一般由具体锁实现类实现,AQS本身没有这个概念。就拿ReentranLock来说,它内部的公平锁与非公平锁的区别在于获取锁是否严格遵循排队顺序:

  • 如果锁被其他线程持有,那么再申请锁的其他线程会被挂起等待,加入到等待队列的末端,并遵循先入先出原则排队获取锁,这就是公平锁。
  • 非公平锁则是让当前正在请求的线程优先插队第一个获取锁(不管等待队列是否有其他线程等待获取锁),如果获取到了直接返回,如果获取不到才加入到等待队列的末端。

我们看下ReentranLock独占锁源码便知,公平与非公平下获取锁的不同:

​

结语

我是tin,一个在努力让自己变得更优秀的普通工程师。自己阅历有限、学识浅薄,如有发现文章不妥之处,非常欢迎加我提出,我一定细心推敲并加以修改。

坚持创作不容易,你的正反馈是我坚持输出的最强大动力,谢谢!

原文链接:juejin.cn/post/7051044971625283615

visio安装包 Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。 立即下载

相关推荐

FastAPI + LLM 实战:5分钟搞定本地模型API服务部署(含避坑指南)

本文详细介绍了如何使用FastAPI和LLM(大语言模型)快速部署本地API服务,涵盖环境准备、模型集成、性能优化及避坑指南。通过实战示例,帮助开发者在5分钟内完成从零到生产的部署过程,提升AI应用开发效率。

weixin_29062963的博客 102

并发编程之AQS详解

Java并发编程核心在于java.util.concurrent包(简称juc)。 这整个包的作者都是:doug lea 什么是AQS AQS 是 AbstractQueuedSynchronizer 的简称。AbstractQueuedSynchronizer 是一个抽象类。在 juc 中,常用的那些类(例如ReentrantLock、CountDownLatch、Semaphore),内部都维护了一个Sync对象(同步器),而 Sync 就是继承了 AbstractQueuedSynchron

修理男爵的博客 633

西门子S7-1200与汇川SV660P伺服速度模式实战:从接线到编程全流程

本文详细解析了西门子S7-1200 PLC与汇川SV660P伺服驱动器在速度模式下的集成实战。内容涵盖从硬件接线、伺服参数关键设置(如电子齿轮比)、博图软件组态到PLC编程的全流程,并提供了故障排查与性能优化指南,帮助工程师快速实现精准、稳定的运动控制。

weixin_29248313的博客 482

Java中的AQS

java中的同步

陈德山 2598

时空双重机器学习在环境政策评估中的创新应用

因果推断是数据分析中的核心问题,特别是在环境政策评估领域。传统方法如差异分析法(DID)在处理时空维度上的复杂相关性时存在局限。机器学习技术,特别是双重机器学习(DML),通过分阶段建模有效解决了混杂变量问题。结合贝叶斯加性回归树(BART)的灵活建模能力,可以更准确地捕捉空间和时间模式。这种时空双重机器学习(ST-DML)方法在柬埔寨森林砍伐案例中表现出色,通过Wendland基函数有效处理了空间自相关问题。该技术框架不仅适用于环境政策评估,还可扩展至空气质量、水资源管理等其他领域,为政策制定提供更精准的

weixin_28685045的博客 344

别让你的URDF模型在Gazebo里‘躺平’:手把手教你配置libgazebo_ros_diff_drive插件让两轮小车动起来

本文详细解析了如何在Gazebo中配置libgazebo_ros_diff_drive插件,使两轮小车模型实现动态仿真。从URDF模型到传动装置,再到差速驱动插件的精细调参,手把手教你解决机器人‘躺平’问题,提升ROS1与Gazebo仿真的实战能力。

weixin_42552716的博客 333

java——AQS(AbstractQueuedSynchronizer)

AQS(AbstractQueuedSynchronizer)是Java并发包(java.util.concurrent)中的一个核心组件,是构建锁和其他同步器的基础框架。

oopxiajun博客专栏 2759

Halcon异常检测训练避坑指南:如何避免GPU内存溢出和样本不足问题

本文针对Halcon深度学习异常检测训练中常见的GPU内存溢出和样本不足两大难题,提供了从原理分析到实战解决方案的深度指南。通过调整批次大小、图像尺寸、使用梯度累积等技巧有效管理显存,并利用针对性数据增强与人工合成策略破解小样本困境,帮助开发者构建稳定高效的训练流程。

river的博客 215

Java并发之AQS全面详解

​ AQS全称 AbstractQueuedSynchronizer,即抽象的队列同步器,是一种用来构建锁和同步器的框架。基于AQS构建同步器:优势:2.1 AQS核心思想  如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。如图所示:Sync queue: 同步队列,是一个双向列表。包括head节点和t

JavaShark的博客 1万+

西门子G120变频器在立体仓库堆垛机应用参数设置

本文详细介绍了G120 CU240E及CU250S变频器的参数设置流程。主要内容包括:1)快速调试步骤,从新建项目、扫描节点到设置电机类型、负载类型等参数;2)抱闸参数设置方法;3)参数下载异常时的处理方案。重点说明了通过STARTER软件进行向导式调试的完整过程,包括电机铭牌参数输入、识别方式选择等关键环节,并提示了通讯连接注意事项。当下载失败时,提供了通过导入导出项目文件解决问题的具体方法。

xdpcxq的专栏 863

三维重建(十三)——多视角重建

本文综述了多视角三维重建技术,涵盖静态和动态场景的重建方法。介绍了从图像获取到纹理映射的SFM流程,以及非刚性重建(NRSFM)的挑战和解决方案。重点探讨了基于可微渲染的重建方法,以及数据采集策略、相机标定和同步技术。文章还讨论了如何用单视角相机模拟多视角重建,总结了关键技术和未来研究方向。

河海大学研究生在读的学习笔记 1058

Java并发编程第六篇(AQS设计理念与源码解析)

在JUC中, 我认为最核心的组件便是AQS, 可以这么理解, AQS是对CAS的一种封装和丰富, AQS引入了独占锁、共享锁等性质。基于AQS, JUC中提供了更多适用于各种预设场景的组件, 当然你也可以基于AQS开发符合自身业务场景的组件。所以, AQS作为承下启上的重点, 我们需要仔细来看。

Du_XiaoNan的博客 1107

群无人机航迹规划-虚拟管道

图源北理工全权老师团队虚拟管道相关论文,文字为个人理解,以ppt形式分享报告。

coldmood77的博客 669

Java并发编程之AQS以及源码解析

不同的自定义同步器争用共享资源的方式也不同。自定义同步器在实现时只需要实现共享资源的获取与释放方式即可,至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等),AQS已经在顶层实现好了。方法描述尝试获取独占锁成功则返回true,失败则返回false。尝试释放独占锁成功则返回true,失败则返回false。尝试获取共享锁负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。尝试释放共享锁成功则返回true,失败则返回false。当前线程是否获得了独占锁。...............

致力于不留技术债务cuizb.top 1083

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

JUC AQS ReentrantLock源码分析(一)

Java的内置锁一直都是备受争议的,在JDK 1.6之前,synchronized这个重量级锁其性能一直都是较为低下,虽然在1.6后,进行大量的锁优化策略,但是与Lock相比synchronized还是存在一些缺陷的:虽然synchronized提供了便捷性的隐式获取锁释放锁机制(基于JVM机制),但是它却缺少了获取锁与释放锁的可操作性,可中断、超时获取锁,且它为独占式在高并发场景下性能大打折扣。...

java_lyvee的专栏 3万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Java并发编程之AQS同步队列

简单解释一下J.U.C,是JDK中提供的并发工具包,java.util.concurrent。里面提供了很多并发编程中很常用的实用工具类,比如atomic原子操作、比如lock同步锁、fork/join等。 从Lock作为切入点 我想以lock作为切入点来讲解AQS,毕竟同步锁是解决线程安全问题的通用手段,也是我们工作中用得比较多的方式。 Lock API Lock是一个接口,方法定义如下 ...

u010600950的博客 902

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

Lock简介与初识AQS

文章目录concurrent包的结构层次Lock简介Lock接口API初识AQSAQS的模板方法设计模式一个例子 concurrent包的结构层次 在针对并发编程中,Doug Lea大师为我们提供了大量实用,高性能的工具类,针对这些代码进行研究会让我们队并发编程的掌握更加透彻也会大大提升我们队并发编程技术的热爱。这些代码在java.util.concurrent包下。如下图,即为concurren...

ThinkWon的博客 1万+

AQS是什么?Java并发编程大师的源码不读必后悔

今天把ReentrantLock和AQS一起翻一翻,通过源码说一说我们的Java锁。 初识ReentrantLock 首先,我们同时启用5个线程对一个公共变量counter从0开始累加,每个线程只对变量+1,理想的情况是公共变量最后值等于5,类似如下结果: thread(0) @【看点代码再上班】, thread state:RUNNABLE thread(1) @【看点代码再上班】, thread state:WAITING thread(2) @【看点代码再上班】, thread state:W

m0_66225491的博客 100

并发编程之核心AQS

AQS核心

qq_42829957的博客 387

结合ReentrantLock对AQS的个人理解

为了加深个人对并发编程的理解,最近把研究原理的目标放在了AQS上~~Doug Lea大师键下的AQS确实非常经典,先来简单介绍一下~~:AQS(全名AbstractQueuedSynchronizer)是Java并发编程中的一个重要类,它提供了一种基于队列的同步机制,用于实现各种同步器(synchronizer)和锁(lock).著名的ReentrantLock(独占模式实现)与Semaphore(共享模式实现)都是由AQS实现(虽然都是Doug Lea大师一个人写的~)

qq_26216881的博客 1723

JDK8的AQS源码学习

1.JDK8AQS源码分析学习 1.1.带着问题学习 1.AQS是什么鬼东西 2.AQS是怎么实现的 1.2.基本介绍 在并发编程中,Doug Lea大师为我们提供了大量实用,高性能的工具类,Doug Lea,concurrent 包的作者,编程不识Doug Lea,写尽java也枉然。 // 同步队列,是一个带头结点的双向链表,用于实现锁的语义 public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchron.

道阻且长,行则将至。 411

一文带你读懂AQS

AQS(AbstractQueuedSynchronizer)是Java并发编程的核心框架,提供了一套通用的线程同步机制。它通过原子状态变量(state)和CLH队列实现资源管理,支持独占(如ReentrantLock)和共享(如Semaphore)两种模式。AQS采用模板方法模式,将线程排队、阻塞/唤醒等通用逻辑封装,具体资源获取/释放由子类实现。源码分析显示其核心流程包括:获取资源时先尝试快速获取,失败则进入队列自旋等待;释放资源时唤醒后续节点。AQS还通过ConditionObject实现条件等待机制

qq_844085127的博客 1209

Java并发编程的艺术(八)——初识Lock与AbstractQueuedSynchronizer(AQS)

1. concurrent包的结构层次 在针对并发编程中,Doug Lea大师为我们提供了大量实用,高性能的工具类,针对这些代码进行研究会让我们队并发编程的掌握更加透彻也会大大提升我们对并发编程技术的热爱。这些代码在java.util.concurrent包下。如下图,即为concurrent包的目录结构图。 其中包含了两个子包:atomic以及lock,另外在concurrent下的阻塞...

qq_42499188的博客 216

深入解析 Java 8 中的 AbstractQueuedSynchronizer(AQS):原理、应用与源码分析

在 Java 多线程编程中,同步是确保线程安全的关键。Java 并发包(java.util.concurrent)提供了许多高级工具,如 ReentrantLock、Semaphore 和 CountDownLatch,这些工具的底层都依赖于一个强大的框架——AbstractQueuedSynchronizer(AQS)。AQS 由并发大师 Doug Lea 设计,是 Java 并发包的核心组件之一。它通过一个原子整数状态(state)和 FIFO 等待队列管理线程竞争,提供了独占和共享两种同步模式。

持续输出Java相关知识 1021

【并发编程】通过ReentrantLock学习AQS

通过ReentrantLock学习AQS 文章目录通过ReentrantLock学习AQS1. AQS基础1.1 state变量--AQS强拓展性的体现1.2 AQS队列节点的数据结构定义1.3 native方法对于AQS的支持2. 可重入锁(ReentrantLock)获取和释放2.1 队列同步器2.2 获取锁2.3 释放锁2.4 公平和非公平的区别2.5 使用AQS自己实现一个同步工具 java并发包(java.util.concurrent)是jdk提供的功能强大拓展性很强的一个并发管理的工具类,主要

完美的工程学 345

深入浅出,从 ReentrantLock 到 AQS | Java

引言 如果问一个 Android 同学,请你简单说一下 Java AQS 的基本思想,那么有不少于一半的同学可能是懵逼状态????。 什么玩意,AQS 是什么,我咋没听过????。 的确,对于非Java后端同学来说,没听过倒也不是什么太过分的事,但是如果你深入学习过 Java 并发相关,那么肯定会去了解各种锁,而作为一个 有志青年 的你必然会在心里来一句,为什么加了锁就可以同步 ? 此时必然也会看到 AQS 的影子。 从技术的角度讲,当我们谈到 ReentrantLock ,不难也会说到 AQS 。 如

petterp的博客 643
上一篇: Java异步编程的核心类:FutureTask
下一篇: Spring切面加解密MySQL数据实战
superjava_
博客等级 码龄5年 254粉丝 81原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值