Semaphore用例、源码分析讲解
时间:2020-06-10
本文章向大家介绍Semaphore用例、源码分析讲解,主要包括Semaphore用例、源码分析讲解使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
semaphore 也就是我们常说的信号灯,semaphore 可以控制同时访问的线程个数,通过 acquire 获取一个许可,如果没有就等待,通过 release 释放一个许可。有点类似限流的作用。叫信号灯的原因也和他的用处有关,比如某商场就 5 个停车位,每个停车位只能停一辆车,如果这个时候来了 10 辆车,必须要等前面有空的车位才能进入。
使用案例
public static void main(String[] args) {
Semaphore semaphore=new Semaphore(5);
for(int i=0;i<10;i++){
new Car(i,semaphore).start();
}
}
static class Car extends Thread{
private int num;
private Semaphore semaphore;
public Car(int num, Semaphore
semaphore) {
this.num = num;
this.semaphore = semaphore;
}
public void run(){
try {
semaphore.acquire();//获取一个许可
System.out.println("第"+num+"占用一个停车位");
TimeUnit.SECONDS.sleep(2);
System.out.println("第"+num+"俩车走喽");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
使用场景
Semaphore 比较常见的就是用来做限流操作了。
Semaphore 源码分析
从 Semaphore 的功能来看,我们基本能猜测到它的底层实现一定是基于 AQS 的共享所,因为需要实现多个线程共享一个领排池创建 Semaphore 实例的时候,需要一个参数 permits,这个基本上可以确定是设置给 AQS 的 state 的,然后每个线程调用 acquire 的时候,行 state = state - 1,release 的时候执行 state = state + 1,当然,acquire 的时候,如果 state = 0,说明没有资源了,需要等待其他线程 release。
Semaphore 分公平策略和非公平策略 :
FairSync:
static final class FairSync extends Sync {
private static final long serialVersionUID = 2014338818796000944L;
FairSync(int permits) {
super(permits);
}
protected int tryAcquireShared(int acquires) {
for (; ; ) { // 区别就在于是不是会先判断是否有线程在排队,然后才进行 CAS 减操作
if (hasQueuedPredecessors())
return -1;
int available = getState();
int remaining = available - acquires;
if (remaining < 0 || compareAndSetState(available, remaining))
return remaining;
}
}
}
NofairSync :
通过对比发现公平和非公平的区别就在于是否多了一个hasQueuedPredecessors 的判断。
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); } } final int nonfairTryAcquireShared(int acquires) { for (; ; ) { int available = getState(); int remaining = available - acquires; if (remaining < 0 || compareAndSetState(available, remaining)) return remaining; } }
由于后面的代码和 CountDownLatch 的是完全一样,都是基于共享锁的实现,所以也就没必要再花时间来分析了。
至此,Semaphore 讲解就结束了,希望朋友们能领悟一些知识。
原文地址:https://www.cnblogs.com/47Gamer/p/13083667.html
- SDIBT 1046 Primary Arithmetic
- 洛谷P2415 集合求和
- React多页面应用5(webpack生产环境配置,包括压缩js代码,图片转码等)
- SDIBT 1046 Primary Arithmetic
- React多页面应用4(webpack自动化生成多入口页面)
- 第二周神经网络基础2.1 二分分类2.2 logistic回归2.3 logistic 回归损失函数2.4 梯度下降2.5 导数2.14 向量化logistic 回归的输出2.15 Python中的广
- 1031 SDIBT Where's Waldorf?
- poj 2469 Stack 'em Up
- React多页面应用3(webpack性能提升,包括打包性能、提取公共包等)
- POJ 2646 The Trip
- React多页面应用2(处理CSS及图片,引入postCSS,及图片处理等)
- 图的广度优先搜索和深度优先搜索(邻接链表表示)邻接链表广度优先搜索深度优先搜索运行结果
- JOJ 2680 Problem F: Coin Game
- React多页面应用1(webpack开发环境搭建,包括Babel、热更新等)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【程序中的数学】利用德摩根定律简化布尔运算
- Conjob For hybris
- ListView通用泛型适配器
- Android实现C/S聊天室
- OpenCV4.4 CUDA编译与加速全解析
- 如何利用Kotlin实现极简回调
- Android辅助权限的介绍和配置完整记录
- Redis基础——剖析基础数据结构及其用法
- SwipeRefreshLayout+RecyclerView实现上拉刷新和下拉刷新功能
- 二值分析 | OpenCV + skimage如何提取中心线
- 详解OpenVINO 模型库中的人脸检测模型
- Tensorflow的妙用
- 终端抓包神器 | tcpdump参数解析及使用
- GoLang 中发送 email 邮件
- 漫画算法题:两数之和与三数之和