信号量是什么

本文介绍了信号量作为同步机制在多线程并发控制中的作用,比较了与限流的区别,展示了JavaSemaphore的使用示例,以及其基于AQS的内部实现原理和队列等待机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

信号量

信号量是什么

信号量是一种用于控制对共享资源的访问的同步机制,他可以限制同时访问共享资源的线程数量,从而避免资源的竞争和冲突。
使用场景:用于多线程的并发控制,类似于限流。

信号量和限流的异同

信号量和限流的使用场景侧重点不同:
  1. 信号量通常用于控制对共享资源的访问;
  2. 限流用于控制系统的输入和输出流量,防止系统过载;
关注的维度不同
  1. 限流通常是接口维度或系统维度的,一般是分布式下控制的;
  2. 信号量是单机节点下控制的线程并发。

相似之处,都涉及对资源或流量的控制,以保证系统的稳定性;

信号量怎么用

信号量可以使用 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 的核心思想是通过内置的队列和状态来实现线程的阻塞和唤醒,从而实现对共享资源的访问控制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值