0

0

Java中信号量的作用 解析Semaphore限制并发数的原理

裘德小鎮的故事

裘德小鎮的故事

发布时间:2025-06-30 22:01:06

|

793人浏览过

|

来源于php中文网

原创

信号量在java中主要用于控制共享资源的并发访问数量,其核心原理是通过维护许可计数器限制线程访问。1. 初始化时设定许可数量,代表可用资源数;2. 线程调用acquire()获取许可,若许可充足则继续执行并减少计数器,否则阻塞等待;3. 线程完成任务后调用release()释放许可,唤醒等待线程。公平性可通过构造函数设置,确保请求顺序或允许插队。使用示例中通过semaphore限制最多3个线程并发执行任务,模拟了数据库连接池等场景。与锁相比,semaphore更通用,支持多线程访问而非仅单一线程。为避免死锁,需注意获取顺序一致、设置超时机制及异常下资源释放。应用场景包括流量控制、资源限制及有界队列实现,帮助构建高效稳定的并发程序。

Java中信号量的作用 解析Semaphore限制并发数的原理

信号量在Java中主要用于控制对共享资源的并发访问数量,就像交通信号灯控制道路上的车辆数量一样,确保资源不会因为过度并发而崩溃。它通过维护一个许可计数器来实现这一点,线程必须先获取许可才能访问资源,访问完毕释放许可。

Java中信号量的作用 解析Semaphore限制并发数的原理

Semaphore限制并发数的原理

Java中信号量的作用 解析Semaphore限制并发数的原理

Semaphore的核心在于它的许可(permit)计数器。初始化时,你可以设置这个计数器的初始值,代表可用的许可数量。

立即学习Java免费学习笔记(深入)”;

Java中信号量的作用 解析Semaphore限制并发数的原理
  1. 获取许可(acquire): 当一个线程想要访问共享资源时,它会尝试调用acquire()方法来获取一个许可。
    • 如果许可计数器大于0,线程成功获取许可,计数器减1。线程可以继续执行。
    • 如果许可计数器等于0,线程会被阻塞,直到有其他线程释放许可。
  2. 释放许可(release): 当线程完成对共享资源的访问后,它会调用release()方法来释放许可。
    • 许可计数器加1。
    • 如果有其他线程因为等待许可而被阻塞,那么其中一个线程会被唤醒,并获取许可继续执行。

Semaphore的公平性可以通过构造函数指定。公平信号量会按照线程请求许可的顺序来分配许可,而非公平信号量则允许“插队”,即如果一个线程恰好在许可可用时尝试获取,即使有其他线程在等待,它也可能先获取到许可。

Java中如何使用Semaphore?

import java.util.concurrent.Semaphore;

public class SemaphoreExample {

    private static final int MAX_PERMITS = 3; // 最大并发数
    private static Semaphore semaphore = new Semaphore(MAX_PERMITS, true); // 公平锁

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(new Task(i)).start();
        }
    }

    static class Task implements Runnable {
        private int taskId;

        public Task(int taskId) {
            this.taskId = taskId;
        }

        @Override
        public void run() {
            try {
                System.out.println("Thread " + taskId + " is waiting for permit.");
                semaphore.acquire();
                System.out.println("Thread " + taskId + " acquired permit.");
                // 模拟耗时操作
                Thread.sleep((long) (Math.random() * 1000));
                System.out.println("Thread " + taskId + " is releasing permit.");
                semaphore.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在这个例子中,我们创建了一个最多允许3个线程同时访问的信号量。每个线程在执行任务前都需要先获取许可,执行完毕后释放许可。

免费语音克隆
免费语音克隆

这是一个提供免费语音克隆服务的平台,用户只需上传或录制一段 5 秒以上的清晰语音样本,平台即可生成与用户声音高度一致的 AI 语音克隆。

下载

Semaphore与锁(Lock)的区别是什么?

锁(例如ReentrantLock)通常用于保护临界区,确保同一时间只有一个线程可以访问。Semaphore则更通用,它可以控制多个线程同时访问共享资源的数量。锁本质上是许可数量为1的信号量。

假设你有一个数据库连接池,你希望限制同时连接到数据库的线程数量,这时Semaphore就非常有用。而如果你只是想保护一个共享变量,防止并发修改,那么锁可能更合适。

如何避免Semaphore的死锁问题?

死锁是并发编程中常见的问题,Semaphore也不例外。要避免死锁,需要注意以下几点:

  1. 避免循环等待: 线程获取多个信号量的顺序要一致。如果线程A先获取信号量S1,再获取S2,那么其他线程也应该遵循相同的顺序。
  2. 设置超时时间: acquire()方法有带超时时间的版本,例如acquire(long timeout, TimeUnit unit)。如果线程在指定时间内没有获取到许可,可以放弃等待,避免永久阻塞。
  3. 资源释放: 确保在任何情况下,线程都能释放已经获取的信号量,即使发生异常。可以使用try-finally块来保证释放操作的执行。
try {
    semaphore.acquire();
    // ... 执行操作 ...
} catch (InterruptedException e) {
    // ... 处理中断 ...
} finally {
    semaphore.release();
}

Semaphore在实际开发中的应用场景有哪些?

除了数据库连接池,Semaphore还可以用于:

  • 流量控制: 限制某个接口的并发请求数量,防止服务过载。
  • 资源限制: 限制对文件、网络连接等资源的并发访问。
  • 实现有界队列: 可以使用Semaphore来控制队列的容量,防止队列无限增长。

总的来说,Semaphore是一个强大的并发控制工具,理解它的原理和使用方法,可以帮助你编写更健壮、更高效的并发程序。当然,并发编程本身就比较复杂,需要仔细考虑各种边界情况和潜在的问题。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1923

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

656

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2392

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

47

2026.01.19

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

765

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

377

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

32

2026.01.21

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

29

2026.01.21

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

3

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 6万人学习

Pandas 教程
Pandas 教程

共15课时 | 1.2万人学习

ASP 教程
ASP 教程

共34课时 | 5.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号