Java多线程 之 Semaphore源码分析

Semaphore 源码解析 Semaphore 源码解析 通过使用Semaphore可以在高并发场景进行限流控制处理 立即下载

​目录

               1、背景介绍

               2、源码分析


一、背景介绍

信号量(Semaphore),也被称为信号量,是在多线程环境下使用的一种工具类, 它负责协调各个线程, 以保证它们能够以一定数量地、正确、合理的使用公共资源。

每一个线程获取到一个计数信号量后,计数信号量就会减1,知道计数信号量为0,表示计数信号量已经不可用了,在许可可用前会阻塞每一个 acquire()。。拿到信号量的线程可以进入代码,否则就等待。通过acquire()和release()获取和释放访问许可。

二、源码分析

Semaphore的实现其实也并不复杂。它的源码当中可以发现其核心功能是使用AQS进行实现的。

首先我们看其构造方法。

public Semaphore(int permits) {
        sync = new NonfairSync(permits);
    }

sync和NonfairSync应该已经很熟悉了,如果了解AQS框架的话。

private final Sync sync;
​
    /**
     * Synchronization implementation for semaphore.  Uses AQS state
     * to represent permits. Subclassed into fair and nonfair
     * versions.
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 1192457210091910933L;
​
        Sync(int permits) {
            setState(permits);
        }
​
        final int getPermits() {
            return getState();
        }
​
        final int nonfairTryAcquireShared(int acquires) {
            for (;;) {
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }
​
        protected final boolean tryReleaseShared(int releases) {
            for (;;) {
                int current = getState();
                int next = current + releases;
                if (next < current) // overflow
                    throw new Error("Maximum permit count exceeded");
                if (compareAndSetState(current, next))
                    return true;
            }
        }
​
        final void reducePermits(int reductions) {
            for (;;) {
                int current = getState();
                int next = current - reductions;
                if (next > current) // underflow
                    throw new Error("Permit count underflow");
                if (compareAndSetState(current, next))
                    return;
            }
        }
​
        final int drainPermits() {
            for (;;) {
                int current = getState();
                if (current == 0 || compareAndSetState(current, 0))
                    return current;
            }
        }
    }
​
    /**
     * NonFair version
     */
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = -2694183684443567898L;
​
        NonfairSync(int permits) {
            super(permits);
        }
​
        protected int tryAcquireShared(int acquires) {
            return nonfairTryAcquireShared(acquires);
        }
    }
​
    /**
     * Fair version
     */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = 2014338818796000944L;
​
        FairSync(int permits) {
            super(permits);
        }
​
        protected int tryAcquireShared(int acquires) {
            for (;;) {
                if (hasQueuedPredecessors())
                    return -1;
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }
    }

以上就是基于AQS的实现。至于AQS这里不做重点讲解。下面我们来看本例中使用到的一些方法(acquire和release),对其源码进行分析。

 // 获取许可证
   semaphore.acquire()
​
   public void acquire() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    } 
​
    public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (tryAcquireShared(arg) < 0)
            doAcquireSharedInterruptibly(arg);
    }  

这是一种在共享模式下、响应中断地获取共享资源方式。它会获取指定量的资源,获取成功则直接返回,获取失败则进入等待队列,直到获取到资源为止,整个过程响应中断。

首先Thread.interrupted判断线程是否被中断,如果中断则直接抛出异常结束。tryAcquireShared依然是AQS的顶层接口,需要实现者自己去实现,Semaphore的实现逻辑如下。

 protected int tryAcquireShared(int acquires) {
            return nonfairTryAcquireShared(acquires);
        }
        final int nonfairTryAcquireShared(int acquires) {
            for (;;) {
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }

首先使用getState获取available可用资源,然后available可用资源数量减去acquires要申请的资源数量,如果返回为负,表示剩余可用资源少于请求占用资源数量,否则返回剩余可用资源数量或者全部资源已经都被占用(remaining为0)。

然后doAcquireSharedInterruptibly方法表示在剩余可用资源少于请求占用资源数量的情况下让线程进行等待资源被释放。

/**
     * Acquires in shared interruptible mode.
     * @param arg the acquire argument
     */
    private void doAcquireSharedInterruptibly(int arg)
        throws InterruptedException 
        //添加到队列尾部
        final Node node 
        //标志是否获取成功
        boolean failed = true;
        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
                        failed = false;
                        return;
                    }
                }
                //状态检查是否k可以park进行park操作
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    throw new InterruptedException();
            }
        } finally {
            //如果fail为true,取消获取操作
            if (failed)
                cancelAcquire(node);
        }
    }

在共享可中断模式下进行等待资源被释放,这段代码执行逻辑注释已经标明,最终执行park操作之后线程就进入阻塞状态了。

接下来看第二个方法release的使用原理。

public void release() {
        sync.releaseShared(1);
    }
​
    public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }

Semaphore直接调用sync的releaseShared方法,默认参数arg为1。

tryReleaseShared尝试去释放共享资源,这个具体释放逻辑需要实现者根据需要去实现。

  protected boolean tryReleaseShared(int arg) {
        throw new UnsupportedOperationException();
    }
​
       //Semaphore的实现方式
       protected final boolean tryReleaseShared(int releases) {
            for (;;) {
                int current = getState();
                int next = current + releases;
                if (next < current) 
                    // 数量溢出
                    throw new Error("Maximum permit count exceeded");
                if (compareAndSetState(current, next))
                    return true;
            }
        }

Semaphore的实现方式并不复杂,getState获取current然后和释放数量releases进行相加,然后对releases进行合法性校验,接着CAS自旋的方式进行赋值state同步变量。如果成功返回true就可以唤醒后续的线程了。

doReleaseShared主要用于唤醒后继线程。

private void doReleaseShared() {
        /*
         * Ensure that a release propagates, even if there are other
         * in-progress acquires/releases.  This proceeds in the usual
         * way of trying to unparkSuccessor of head if it needs
         * signal. But if it does not, status is set to PROPAGATE to
         * ensure that upon release, propagation continues.
         * Additionally, we must loop in case a new node is added
         * while we are doing this. Also, unlike other uses of
         * unparkSuccessor, we need to know if CAS to reset status
         * fails, if so rechecking.
         */
        for (;;) {
            Node h = head;
            if (h != null && h != tail) {
                int ws = h.waitStatus;
                if (ws == Node.SIGNAL) {
                    //如果赋值失败就循环执行  
                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                        continue;  
                    //唤醒后继              
                    unparkSuccessor(h);
                }
                else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                    continue;                // loop on failed CAS
            }
            if (h == head)                   // loop if head changed
                break;
        }
    }

Node.SIGNAL表示结点Node的状态:

需要补加一点的是共享模式下的releaseShared()拥有资源的线程在释放掉部分资源时就可以唤醒后继等待结点。这一点是和独占模式下释放资源不同的一点。

至此,Semaphore在本例中的应用源码分析就分析完了,如果理解AQS框架下共享、独占模式下获取、释放共享资源原理的话对于本例中的执行原理应该还是很容易的。

 

更多内容持续更新中,感兴趣的朋友请移步至个人公众号,谢谢支持😜😜......

公众号:wenyixicodedog

Java并发系列之Semaphore源码分析 主要为大家详细介绍了Java并发系列之Semaphore源码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 立即下载

相关推荐

树莓派CSI/DSI二合一接口深度玩法:同时驱动MIPI摄像头和屏幕的配置秘籍

本文详细解析了树莓派5上CSI/DSI二合一接口的深度玩法,提供了同时驱动MIPI摄像头和屏幕的完整配置秘籍。从硬件连接到软件设置,包括config.txt的优化配置,帮助用户充分利用树莓派5的双多功能接口,实现高效的双设备工作模式。

weixin_30687051的博客 573

Semaphore 源码解读

通过阅读Semaphore的源码可以发现,大量依赖于AQS中提供的方法,如果有阅读过ReentrantLock 锁源码的分析,可以发现相似度极高,都是使用AQS所提供的的特征实现某些场景的应用。

小毕超博客 786

比例导引算法详解:从理论到Matlab实现(含3D轨迹可视化)

本文深入解析比例导引算法(PNG)的数学原理与Matlab实现,涵盖3D轨迹可视化技术。从基础运动学模型到导航比优化,详细讲解导弹拦截系统的核心算法,并提供Matlab代码示例,帮助读者掌握从理论到实战的全流程。

weixin_33725722的博客 548

java多线程之Semaphore源码解析

前言 本篇开始分析Semaphore(信号量)的源码,分析结束后,会用一个示例展示Semaphore的应用场景。 1、简介 Semaphore是一个计数信号量,维护了一个信号量许可集。每次调用acquire()都将消耗一个许可,每次调用release()都将归还一个许可。 2、结构图 Semaphore的内部维护了一个Sync内部类,Sync是继承AQS的抽象类,Sync包括两个子类:"公平信号量"FairSync 和 "非公平信号量"NonfairSync。 3、分析源码 3.1、信号量构造函数 pub

夏夜凉月 333

IPC-7351标准实战:如何用LPWizard_10快速生成PCB封装库(附避坑指南)

本文提供了一份详细的IPC-7351标准实战指南,手把手教你使用LPWizard_10软件快速生成符合行业标准的PCB封装库,并直接导入Cadence Allegro。文章深入解读了IPC-7351密度等级的选择逻辑,并重点分享了软件配置、QFN封装生成实战步骤,以及导出失败、焊盘异常等常见问题的避坑解决方案,旨在帮助硬件工程师提升设计效率和可靠性。

weixin_29207439的博客 153

RDMA网络通信技术、NCCL集合通讯(GPU)

NCCL 是 NVIDIA 专为 GPU 设计的高性能集合通信库,用于优化多 GPU、多节点间的集体操作(如 AllReduce、Broadcast、AllGather 等),是深度学习分布式训练的核心组件。RDMA 允许计算机直接访问远程内存,无需 CPU 干预,大幅降低了网络通信的延迟和 CPU 开销。常见的 RDMA 实现包括。是两项关键技术,用于优化节点间数据传输效率和大规模并行计算性能。在高性能计算(HPC)、人工智能训练和数据密集型场景中,

weixin_42795092的博客 2422

Java Semaphore 信号量的源码深度解析与应用

详细介绍了Semaphore信号量的原理和应用,以及与CountDownLatch的对比!

终生学习践行者 3385

《派出你的AI同事:WorkBuddy案例实战》062:投研资讯摘要与预警

投研资讯摘要与预警:新闻、公告、行情交给 AI 同事提炼与预警,投研从“刷资讯”变成“读摘要”。

LuckyHanMo的博客 182

Java并发编程(十四):Semaphore源码逐行深度分析

使用 Semaphore即信号量,可以控制并发访问特定的资源的线程的数量,比如可用于接口请求限流,和ReentrantLock一样依赖AQS实现,使用的话比较简单: Semaphore semaphore = new Semaphore(10); thread-0: semaphore.acquire(); //do somethis...... semaphore.release(); thread-1: semaphore.acquire(); //do somethis...... semaphor

黄智霖的博客 5064

【机器学习】随机森林(Random Forest,简称 RF):预测光伏电站功率 || 缺失数据处理 || 重复行处理...

【机器学习】随机森林(Random Forest,简称 RF):预测光伏电站功率。

追光者♂:记录、分享、总结、提升,现象级专栏《Python从入门到人工智能》作者,无惧黑暗,坚信曙光 1647

安装 miniconda linux

安装 miniconda linux

jacke121的专栏 1万+

java多线程 Semaphore源码分析

简介 package java.util.concurrent; import java.util.Collection; import java.util.concurrent.locks.AbstractQueuedSynchronizer; /** * 计数信号量。从概念上讲,一个信号量维护一组许可。 * 如果有必要,每个acquire阻塞直到一个许可可用,然后获取它。 * 每次release都会增加一个许可,潜在地释放一个阻塞的获取者。 * 但是,没有使用实际的permit对象; *

今天吃了吗的博客 269

【教程4>第6章>第26节】基于FPGA的MMSE信道估计与均衡系统实现与整体测试,并对比LS信道估计

通过前面几个章节的学习,我们完成了MMSE信道估计和均衡系统。为了进一步验证MMSE信道估计的性能,我们在系统的最后,增加一个信道估计误差计算程序。由于MMSE信道估计,其主要优势在SNR较小时提现,因此测试对比时,我们在testbench中,将SNR设置为2db。然后m值,我们不考虑一个固定值,而是一直累加,直到所设置的仿真时间结束。通过对比可以看到,MMSE信道估计性能优于LS信道估计。这样方便FPGA中的误差计算。

FPGA/MATLAB学习教程/源码/项目合作开发 1599

Java多线程系列(十)—Semaphore源码分析

Java多线程系列(十)—Semaphore源码分析 Semaphore是计数信号量,用来控制并发数量,允许n个任务同时访问某个资源,可以将信号量看做是在向外分发使用资源的许可,只有成功获取许可才能使用资源; 个人主页:tuzhenyu’s page 原文地址:Java多线程系列(十)—Semaphore源码分析 (0) Semaphore信号量的使用 三个线

tuzhenyu的博客 366

OV9734 DATASHEET,完整规格书

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

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

JUC并发—AQS源码分析三

CountDownLatch允许一个或多个线程等待其他线程完成操作。CountDownLatch提供了两个核心方法,分别是await()方法和countDown()方法。CountDownLatch.await()方法让调用线程进行阻塞进入等待状态,CountDownLatch.countDown()方法用于对计数器进行递减。CountDownLatch在构造时需要传入一个正整数作为计数器初始值。线程每调用一次countDown()方法,都会对该计数器减一。

sdgfafg_25的博客 847

深度学习工具包 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_Semaphore源码分析

Semaphore 顾名思义 就是信号量的意思,是基于AQS 的一个类Semaphore 维护了一个许可集合,在创建Semaphore的时候,设置上许可数,每条线程在只有在获得一个许可的时候才可以继续往下执行逻辑,申请多少许可,Semaphore的许可池中减少多少许可,当没有许可 或 许可不够的时候,申请许可的线程就会进入阻塞状态(加入阻塞队列)。Semaphore 信号量,通常用于控制同一时刻对共享资源的访问,也就是限流场景;Semaphore 的内部实现是就与AQS的共享锁来实现的;

一起加油!!! 287

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Java多线程 -- JUC包源码分析9 -- AbstractQueuedSynchronizer深入分析-- Semaphore与CountDownLatch

在前面分析ReentrantLock/ReentrantReadWriteLock的时候,我们已经对AQS进行过分析。在初步了解了AQS之后,本篇试图对其进行一个更为系统性的分析。因为AQS是为整个同步框架的基石,不光是锁,很多其他同步组件,比如Semaphore, CountDownLatch,也都是建立在AQS之上。 -AQS–同步框架的基石 -AQS的3个核心技术原理 –AQS源码解析

软件开发与架构领域 -体系化知识分享 1797

java 进阶笔记线程与并发之线程计数与同步工具

简介 常见的线程计数和信息同步工具如下: CountDownLatch(一次性栅栏)、Semaphore(信号量)、CyclicBarrier(循环同步栅栏)、Exchanger(线程间交换器)和Phaser(灵活可重用同步栅栏)。 示例 import org.junit.Test; import java.util.concurrent.*; import java.util.concurr...

huitoukest的专栏 438

J.U.C-三剑客[semaphore\CyclicBarrier\CountDownLatch]

一.semaphore信号量,底层也是基于AQS 使用: /** * 可以理解为控制某个资源最多有多少个线程同时执行,(比如洗手间,并行与排队) * 如果满了只能等待直到其它资源释放(可以理解为并发量控制) * @author Binglong * @date 2018-11-12 */ public class SemaphoreUtils { public...

weixin_30518397的博客 147

JUC多线程:CountDownLatch、CyclicBarrier、Semaphore 同步器原理

一、CountDownLatch:1、什么是 CountDownLatch:CountDownLatch,闭锁,就是一个基于 AQS 共享模式的同步计数器,它内部的方法都是围绕 AQS 实现的。主要作用是使一个或一组线程在其他线程执行完毕之前,一直处于等待状态,直到其他线程执行完成后再继续执行。CountDownLatch 利用 AQS 的 state 变量充当计数器(由 volatile 修饰并...

Java知音 325

CountDownLatch、CyclicBarrier和Semaphore

前言 学习了aqs源码之后,我觉得很有必要把这三个类再系统的学习一下, 同时记录下学习的过程。如果没有看过aqs独占锁和aqs共享锁的源码,我建议你先去学习aqs。aqs是基础,这三个类只是Doug Lea为了满足多线程编程下各种线程按照需要的场景来运行而写的三个工具类。aqs不懂,学习这三个类也只是走马观花,不得精髓。水平有限,文章中有误的地方也请不吝指正,互相帮助,共同学习。 CountDownLatch CountDownLatch是我在项目中用的最多的一个并发类,现在我更喜欢用Completable

weixin_43727164的博客 492

多线程与高并发(1)- 线程基础、并发特性、锁、JUC工具

文章目录第一章、线程基础知识一、基础概念1、什么是程序?2、什么是进程?3、什么是线程?4、什么是线程的切换(Context Switch)?5、单核CPU 设定多线程是否有意义?6、工作线程数是不是设置的越大越好?7、工作线程数(线程池中线程数量)设多少合适?二、创建线程的3 种方法1、继承Thread类 重写run方法2、实现Runnable接口 重写run方法3、实现Callable 重写call方法,配合FutureTask4、基于线程池构建线程三、线程状态四、线程的常用方法1、获取当前线程2、线程

qq_32091929的博客 1621

java并发业务场景_JAVA并发编程之多线程并发同步业务场景与解决方案

Java并发编程是一个很热点的话题,无论在面试时候还是在高并发的场景中。都会涉及到Java的并发编程相关的知识。Java的并发编程有两个主要的基础知识,一个是线程安全另一个是线程间通信。本Java并发编程系列博客作为博主系统学习Java并发编程的知识记录。也希望可以帮助其他人。JAVA并发编程之多线程并发同步业务场景与解决方案s1.jpeg (27.24 KB, 下载次数: 0)2020-9-8 ...

weixin_35792040的博客 299

高并发基础之Java并发包

转自:https://www.cnblogs.com/sessionbest/articles/8689297.html 摘要: 本系列基于炼数成金课程,为了更好的学习,做了系列的记录。 本文主要介绍: 1.各种同步控制工具的使用 2.并发容器及典型源码分析 在[高并发Java 二] 多线程基础中,我们已经初步提到了基本的线程同步操作。这次要提到的是在并发包中的同步控制工具。 1. 各种同步...

robinson_911的专栏 167

JAVA并发9.AQS共享模式与并发工具类的实现

CountDownLatch CountDownLatch 这个类是比较典型的 AQS 的共享模式的使用,这是一个高频使用的类。latch 的中文意思是门栓、栅栏,具体怎么解释我就不废话了,大家随意,看两个例子就知道在哪里用、怎么用了。 CountDownLatch所描述的是”在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待“。在API中是这样描述的: 用给定的计数 初始化 ...

qq_38311489的博客 239
上一篇: seata源码初始启动报错(protobuf)
下一篇: springboot 设置跨域
wenyixicodedog
博客等级 码龄8年 87粉丝 116原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值