信号量Semaphore
一、Semaphore是什么?
Semaphore,俗称信号量,它是操作系统中PV操作的原语在java中实现。
基于AbstractQueuedSynchronizer实现!
Semaphore的功能非常强大,大小为1的信号量就类似于互斥锁,通过同时只能有一个线程获取信号量来实现。
大小为n(n>0)的信号量可以实现限流的功能,它可以实现只能有n个线程同时获取信号量。
二、PV操作是什么?
PV操作是操作系统一种实现进程互斥与同步的有效方法。
PV操作与信号量(S)的处理有关,P表示通过的意思,V表示释放的意思
用PV操作来管理共享资源时,首先要确保PV操作自身执行的正确性。
P操作的主要动作:
S减1;
若S减1后仍大于或等于0,则进程继续执行;
若S减1后小于0,则该进程被阻塞后放入等待该信号量的等待队列中。
V操作的主要动作:
S加1;
若相加后结果大于0,则进程继续执行;
若相加后结果小于或等于0,则从该信号量等待队列中释放一个等待进程。
三、Semaphore的使用场景
可以用于做流量控制,特别是公用资源有限的应用场景!
四、Semaphore的使用方式
Sempahore常用方法说明
1. acquire() 获取一个信号量资源,在获取到信号量资源前或者被其他线程调用中断之前线程一直处于阻塞状态. 2. acquire(int permits) 与acquire()方法不同的是,获取permits个信号量. 3. acquireUninterruptibly() 获取一个信号量资源,在获取到信号量资源之前线程一直处于阻塞状态(忽略中断). 4. tryAcquire() 尝试获取信号量资源,返回获取信号量成功或者失败,不阻塞线程. 5. availablePermits() 返回可用的信号量数量
6. release() 释放信号量资源,唤醒一个获取信号量不成功的阻塞线程. 7. hasQueuedThreads() 等待队列里是否还存在等待线程. 8. getQueueLength() 获取等待队列里阻塞的线程数. 9. drainPermits() 清空信号量把可用信号量数量置为0,返回清空的信号量数量
Sempahore使用示例
以停车为示例:
功能实现:同一时刻最多只能停10辆车
代码中 new Semaphore(10)表示10个停车位,
package com.chenly.semaphore;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
* 信号量
* @author: chenly
* @date: 2022-11-08 15:52
* @description:
* @version: 1.0
*/
public class Park {
static Semaphore s = new Semaphore(10);
private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) {
for(int i = 0; i < 100; i++) {
new Thread(() -> {
try {
if(s.availablePermits()==0){
System.out.println(FORMATTER.format(new Date())+":"+Thread.currentThread().getName() + "车位不足");
}
System.out.println(FORMATTER.format(new Date())+":"+Thread.currentThread().getName() + "等待入停车库");
s.acquire();
int i1 = new Random().nextInt(10);
System.out.println(FORMATTER.format(new Date())+":"+Thread.currentThread().getName() + "停" + i1 + "秒" );
TimeUnit.SECONDS.sleep(i1);
System.out.println(FORMATTER.format(new Date())+":"+Thread.currentThread().getName() + "停车完毕,出停车库");
s.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, i+"号车").start();
}
}
}
作者:小念
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构