信号量
信号量
信号量是什么
信号量是一种用于控制对共享资源的访问的同步机制,他可以限制同时访问共享资源的线程数量,从而避免资源的竞争和冲突。
使用场景:用于多线程的并发控制,类似于限流。
信号量和限流的异同
信号量和限流的使用场景侧重点不同:
- 信号量通常用于控制对共享资源的访问;
- 限流用于控制系统的输入和输出流量,防止系统过载;
关注的维度不同
- 限流通常是接口维度或系统维度的,一般是分布式下控制的;
- 信号量是单机节点下控制的线程并发。
相似之处,都涉及对资源或流量的控制,以保证系统的稳定性;
信号量怎么用
信号量可以使用 java.util.concurrent.Semaphore 类来实现。
你可以通过创建一个信号量对象,然后使用 acquire() 方法来获取信号量,使用 release() 方法来释放信号量。
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(1); // 创建一个初始值为1的信号量
try {
semaphore.acquire(); // 获取信号量
// 在这里执行需要控制访问的代码
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // 释放信号量
}
}
}
用锁模拟信号量
自己实现模拟实现一个信号量,便于理解内部原理
import java.util.concurrent.locks.ReentrantLock;
public class CustomSemaphore {
private final ReentrantLock lock = new ReentrantLock();
private volatile int permits;
public CustomSemaphore(int initialPermits) {
this.permits = initialPermits;
}
public void acquire() throws InterruptedException {
lock.lock();
while (permits == 0) {
lock.unlock();
Thread.sleep(100); // 休眠一段时间后再尝试获取锁
lock.lock();
}
permits--;
lock.unlock();
}
public void release() {
lock.lock();
permits++;
lock.unlock();
}
}
信号量满的情况下,是线程等待吗?
是的,当信号量满的情况下,线程会进入等待状态,直到有其他线程释放许可为止。
信号量实现的原理是什么?
信号量的原理是使用一个计数器来控制对共享资源的访问,
当线程希望访问共享资源时,需要先获取信号量。
如果信号量的计数器大于0,则线程可以获取该信号量并将计数器减一,表示占用了一个资源;
如果计数器为0,则线程需要等待,直到有其他线程释放资源,使得计数器增加。
当线程访问完共享资源后,需要释放信号量,将计数器加一,表示释放了一个资源,其他等待的线程可以获取信号量继续访问共享资源。
Semaphore 的内部实现
Semaphore 的内部实现基于同步器 AbstractQueuedSynchronizer (AQS)。
AQS 提供了一个框架,可以用来构建不同类型的同步器,Semaphore 就是其中一种。
Semaphore 内部通过 AQS 的 acquire 和 release 方法来实现许可的获取和释放,以及等待队列的管理。
Semaphore 在内部维护一个计数器,用来表示可用的许可数量,通过 AQS 的状态来实现对计数器的操作和线程的阻塞唤醒。
Semaphore是怎么实现队列等待的
Semaphore 内部通过使用 AQS(AbstractQueuedSynchronizer)来实现队列等待。
当线程尝试获取许可时,如果许可数量不足,线程会被加入到 AQS 的等待队列中,然后被阻塞挂起。
当其他线程释放许可时,AQS 会按照特定的策略唤醒等待队列中的线程,使其有机会再次尝试获取许可。
这样就实现了基于队列的等待机制。
AQS(AbstractQueuedSynchronizer)是 Java 中用于构建同步器的框架,
它提供了一种基于 FIFO 等待队列的同步器实现方式,可以用来构建各种类型的同步器,如 ReentrantLock、Semaphore 等。
AQS 的核心思想是通过内置的队列和状态来实现线程的阻塞和唤醒,从而实现对共享资源的访问控制。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决