JUC并发工具类之Semaphore控制并发线程数
首先看看关于Semaphore的UML图:

从上图看,信号量的实现原理与锁类似,是基于AQS的;有公平与非公平之分。当初始的资源数为1时就退化为排它锁了,资源总数即state的初始值,在acquire里对state变量进行CAS减操作,减到0之后,线程阻塞;在release里对state变量进行CAS加操作。
下面简单示范Semaphore的使用:
1)

2)

3)
通过Semaphore的UML图可知,其使用AQS构建其阻塞类,在Java并发基础之AbstractQueuedSynchronizer(AQS) - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)中大致介绍了AQS的模板方法,那么Semaphore是如何利用AQS构建阻塞类的呢?
1、创建信号量对象:
构造方法有两个,
,本文中案例使用第一个构造函数:

最终使用AQS中setState将参数传递给AQS中的state:Semaphore使用AQS类型的同步状态持有当期可用许可的数量。

2、获取acquire

Semaphore类中重写tryAcquireShared方法首先计算剩余许可的数量,如果没有足够的许可,会返回一个值表示获取操作失败。如果还有充足的许可剩余,tryAcquireShared会使用compareAndSetState尝试原子地递减许可的计数。如果成功(这意味着自从许可计数到最后一次看到后都没有被改变过),会返回一个值表示获取操作成功。返回值同样加入了是否运行其他共享获取尝试能否成功的信息,如果可以的话,其他等待的线程同样会解除阻塞。
注意tryAcquireShared方法内部使用无限循环,即无论是否有足够的许可数量,在相应获取操作时,该循环都会终止。尽管任何给定的compareAndSetState调用都可能由于与另一个线程的竞争而失败,但是这种场景它会重试。在重试过合理的次数后,两个终止条件中的一个会变成真。
3、释放release
类似地,跟踪到tryReleaseShared会递增许可计数,潜在地解除等待中的线程的阻塞并不断地重试直到成功地更新。tryReleaseShared的返回值表明释放操作释放可以解除其他线程的阻塞。

JUC并发工具类之Semaphore控制并发线程数的更多相关文章
- Java并发(十五):并发工具类——信号量Semaphore
先做总结: 1.Semaphore是什么? Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源. 把它比作是控制流量的红绿灯,比如XX马路要 ...
- 【Java并发工具类】Semaphore
前言 1965年,荷兰计算机科学家Dijkstra提出的信号量机制成为一种高效的进程同步机制.这之后的15年,信号量一直都是并发编程领域的终结者.1980年,管程被提出,成为继信号量之后的在并发编程领 ...
- Java多线程并发工具类-信号量Semaphore对象讲解
Java多线程并发工具类-Semaphore对象讲解 通过前面的学习,我们已经知道了Java多线程并发场景中使用比较多的两个工具类:做加法的CycliBarrier对象以及做减法的CountDownL ...
- Java并发工具类(四):线程间交换数据的Exchanger
简介 Exchanger(交换者)是一个用于线程间协作的工具类.Exchanger用于进行线程间的数据交换.它提供一个同步点,在这个同步点两个线程可以交换彼此的数据.这两个线程通过exchange方法 ...
- j.u.c系列(10)---之并发工具类:Semaphore
写在前面 Semaphore是一个计数信号量,它的本质是一个"共享锁". 信号量维护了一个信号量许可集.线程可以通过调用acquire()来获取信号量的许可:当信号量中有可用的许可 ...
- 1.3.4 并发工具类CountDownLatch/Semaphore/CyclicBarrier/FutureTask
CountDownLatch的2个用途: 1. 所有线程都到达相同的起跑线后,再一起开始跑(并非同时开始,而是队列中一个唤醒另一个)[此情况需到达起跑线后再调用await()等待其他线程] 2. 所有 ...
- Java并发—并发工具类
在JDK的并发包里提供了几个非常有用的并发工具类.CountDownLatch.CyclicBarrier和Semaphore工具类提供了一种并发流程控制的手段,Exchanger工具类则提供了在线程 ...
- JUC学习笔记--JUC中并发工具类
JUC中并发工具类 CountDownLatch CountDownLatch是我目前使用比较多的类,CountDownLatch初始化时会给定一个计数,然后每次调用countDown() 计数减1, ...
- JUC 常用4大并发工具类
什么是JUC? JUC就是java.util.concurrent包,这个包俗称JUC,里面都是解决并发问题的一些东西 该包的位置位于java下面的rt.jar包下面 4大常用并发工具类: Count ...
随机推荐
- MySQL注入点写webshell的五种方式
0x00 写数据的前提 1,在mysql的配置文件 my.ini 中,secure_file_priv="c:/wamp64/tmp" 被注释 或者 `secure_file_pr ...
- CTF-sql-group by报错注入
本文章主要涉及group by报错注入的原理讲解,如有错误,望指出.(附有目录,如需查看请点右下角) 一.下图为本次文章所使用到 user表,该表所在的数据库为 test 二.首先介绍一下本文章所使用 ...
- 猪齿鱼 Choerodon 的数据初始化设计解析
数智化效能平台猪齿鱼Choerodon 作为一个微服务框架,需要解决微服务数据初始化本身具有的问题和复杂性,同时也需要满足框架本身特有的数据初始化需求,下面为大家介绍一下这方面的设计思想和实现. 微服 ...
- golang中如何退出goroutine
package main import ( "fmt" "runtime" "time" ) func main() { // 用gorou ...
- golang中数组指针和指针数组当做函数参数如何修改数组中的值
先理解:数组指针它的类型时指针,指针数组它的类型时数组 1. 数组指针当做函数的参数 package main import "fmt" func changeData(dataA ...
- Go 面向对象三大特性
#### Go 中面向对象的三大特性上周因为有一些事情,停更了; 停更的这段时间,花了点时间做了一个小项目(https://github.com/yioMe/node_wx_alipay_person ...
- cnpm安装教程
安装cnpm,输入以下命令: sudo npm install -g cnpm --registry=https://registry.npm.taobao.org 输入cnpm -v ,检测是否正常 ...
- 随机UA
from fake_useragent import UserAgent ua = UserAgent().random headers={ 'User-Agent':ua } print(heade ...
- hive 常用日期格式转换
固定日期转换成时间戳select unix_timestamp('2016-08-16','yyyy-MM-dd') --1471276800select unix_timestamp('201608 ...
- Visual Studio 2022 下载链接及激活密钥
Visual Studio 2022 下载链接:https://visualstudio.microsoft.com/zh-hans/vs/ 激活码: 专业版: TD244-P4NB7-YQ6XK-Y ...