”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 使用信号量管理 Java 并发的技术

使用信号量管理 Java 并发的技术

发布于2024-11-09
浏览:284

1. Java中的信号量是什么?

Techniques for Managing Concurrency in Java Using Semaphores

Java 中的信号量是一种同步辅助工具,它限制在任何给定时间可以访问共享资源的线程数量。它是 java.util.concurrent 包的一部分,用于管理对资源(例如文件、数据库或网络连接)的并发访问。

1.1 信号量如何工作?

Techniques for Managing Concurrency in Java Using Semaphores

信号量控制对一定数量的许可的访问。每个许可证代表访问特定资源的权利。信号量跟踪可用许可的数量,这决定了有多少线程可以同时访问资源。

Permit :允许线程继续访问共享资源的令牌或票证。

当您创建信号量时,您指定可用的许可证数量。该数字定义了有多少线程可以同时访问资源。

在线程可以访问资源之前,它必须从信号量获得许可。这是使用 acquire() 方法完成的。

Acquire :当线程想要访问资源时调用此方法。如果许可证可用,则信号量会减少可用许可证的数量并允许线程继续进行。如果没有可用的许可,则该线程将被阻塞,直到有可用的许可为止。

阻塞行为:如果没有可用的许可,调用 acquire() 的线程将被阻塞(即,它将等待),直到另一个线程释放许可。

一旦线程使用完资源,它应该释放许可证以使其可供其他线程使用。这是使用 release() 方法完成的。

Release :此方法会增加可用许可证的数量。如果有任何线程正在等待许可,则其中一个线程将被解除阻塞并允许获取许可。

1.2 信号量的类型

Java中有两种类型的信号量:

  • 计数信号量:这种类型的信号量允许一定数量的线程访问资源。例如,如果将信号量设置为3,则只有三个线程可以同时访问该资源。
  • 二进制信号量(互斥):这是计数信号量的一种特殊情况,其中许可数为 1,一次只允许一个线程访问资源。它经常被用作互斥锁(mutex)。

2. Java中信号量的实现

为了更好地理解信号量的工作原理,让我们看一下实际的实现。我们将创建一个简单的场景,其中多个线程尝试访问有限的资源。

2.1 搭建环境

import java.util.concurrent.Semaphore;

public class SemaphoreDemo {

    // Creating a semaphore with 3 permits
    private static final Semaphore semaphore = new Semaphore(3);

    public static void main(String[] args) {
        // Creating and starting 6 threads
        for (int i = 1; i 



2.2 代码解释

在此示例中,我们创建了一个具有三个许可的信号量,这意味着在任何给定时间只有三个线程可以访问代码的关键部分。然后我们创建六个线程,所有线程都尝试获取许可。一旦线程获得许可,它就会在释放许可之前通过休眠两秒钟来模拟某些工作。

2.3 观察输出

当您运行上面的代码时,输​​出将如下所示:

Worker 1 is trying to acquire a permit...
Worker 1 acquired a permit.
Worker 2 is trying to acquire a permit...
Worker 2 acquired a permit.
Worker 3 is trying to acquire a permit...
Worker 3 acquired a permit.
Worker 4 is trying to acquire a permit...
Worker 5 is trying to acquire a permit...
Worker 6 is trying to acquire a permit...
Worker 1 is releasing a permit.
Worker 4 acquired a permit.
Worker 2 is releasing a permit.
Worker 5 acquired a permit.
Worker 3 is releasing a permit.
Worker 6 acquired a permit.

这里,前三个线程成功获取许可并开始执行任务。其余线程必须等待许可证被释放后才能继续。

2.4 实际用例

信号量在需要限制特定资源并发访问数量的场景中特别有用,例如:

  • 限制数据库连接
  • 控制对共享文件的访问
  • 管理服务器中的网络连接

3. 使用信号量的优点和缺点

虽然信号量是一种强大的工具,但它们也有自己的优点和缺点。

3.1 优点

灵活性:信号量允许精确控制多个线程的资源访问。

可扩展性:信号量可以轻松管理对大量资源的访问。

公平性 :可以配置信号量以确保线程以公平的方式获取许可。

3.2 缺点

复杂性 :使用信号量会给代码带来复杂性,使调试变得更加困难。

死锁:如果处理不当,信号量可能会导致死锁,线程无限期地阻塞等待许可。

4. 在 Java 中使用信号量的最佳实践

为了避免常见陷阱并充分利用信号量,请考虑以下最佳实践:

4.1 使用tryAcquire进行限时获取

您可以使用 tryAcquire() 来尝试获取超时许可,而不是使用无限期阻塞的 acquire() 。这可以防止线程陷入等待状态。

if(semaphore.tryAcquire(1000, TimeUnit.MILLISECONDS)) {
    try {
        // Critical section
    } finally {
        semaphore.release();
    }
}

4.2 始终在finally块中释放许可

为了避免资源泄漏,请始终在 finally 块中释放许可证。这确保即使发生异常也能释放许可证。

4.3 避免使用信号量进行简单锁

如果您只需要为单个线程锁定和解锁资源,请考虑使用ReentrantLock或synchronized而不是二进制信号量。

5. 结论

信号量是 Java 中管理并发的强大工具,允许您控制访问共享资源的线程数量。通过遵循本文中概述的技术和最佳实践,您可以在 Java 应用程序中有效地实现信号量,以确保安全高效的资源管理。

如果您有任何疑问或想分享您自己的信号量经验,请随时在下面发表评论!

阅读更多帖子:使用信号量在 Java 中管理并发的技术

版本声明 本文转载于:https://dev.to/anh_trntun_4732cf3d299/techniques-for-managing-concurrency-in-java-using-semaphores-5ai?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何从 ASP.NET Core Web API 控制器返回文件?
    如何从 ASP.NET Core Web API 控制器返回文件?
    在 ASP.NET Core Web API 中处理文件下载尝试从 ASP.NET Web API 控制器返回文件时,您可能会遇到以下问题:响应被视为 JSON。要解决此问题,了解在 ASP.NET Core 中下载文件的正确方法至关重要。要在 ASP.NET Core Web API 中返回文件,...
    编程 发布于2024-11-09
  • 如何防止 Pandas 在保存 CSV 时添加索引列?
    如何防止 Pandas 在保存 CSV 时添加索引列?
    避免使用 Pandas 保存的 CSV 中的索引列使用 Pandas 进行修改后保存 csv 文件时,默认行为是包含索引列。为了避免这种情况,可以在使用 to_csv() 方法时将索引参数设置为 False。为了详细说明,请考虑以下命令序列:pd.read_csv('C:/Path/to/file....
    编程 发布于2024-11-09
  • 大批
    大批
    方法是可以在对象上调用的 fns 数组是对象,因此它们在 JS 中也有方法。 slice(begin):将数组的一部分提取到新数组中,而不改变原始数组。 let arr = ['a','b','c','d','e']; // Usecase: Extract till index p...
    编程 发布于2024-11-09
  • 除了“if”语句之外:还有哪些地方可以在不进行强制转换的情况下使用具有显式“bool”转换的类型?
    除了“if”语句之外:还有哪些地方可以在不进行强制转换的情况下使用具有显式“bool”转换的类型?
    无需强制转换即可上下文转换为 bool您的类定义了对 bool 的显式转换,使您能够在条件语句中直接使用其实例“t”。然而,这种显式转换提出了一个问题:“t”在哪里可以在不进行强制转换的情况下用作 bool?上下文转换场景C 标准指定了四种值可以根据上下文转换为的主要场景bool:语句:if、whi...
    编程 发布于2024-11-09
  • 如何将移动站点限制为横向并禁用自动旋转?
    如何将移动站点限制为横向并禁用自动旋转?
    增强移动网站体验:强制横向方向并禁用自动旋转在设计移动响应能力时,某些方向可能会对用户产生重大影响经验。此问题寻求一种解决方案,将移动网站限制为横向并禁用自动旋转。CSS 解决方案实现此目的的一种方法是通过 CSS 媒体查询。通过为横向和纵向创建单独的样式表,您可以根据设备的方向控制站点的行为方式。...
    编程 发布于2024-11-09
  • Mac OS X 上的 Python 项目创建
    Mac OS X 上的 Python 项目创建
    介绍 PyFabricate 是一款 Mac OS X 应用程序,可简化 Python 项目的创建。 自从我创作它以来,显然它是我认为 Python 项目应该是什么样子的一个固执己见的版本。 此外,我还有一个特定的工具集,可以用来编写 Python Mac OS X 应用程序。...
    编程 发布于2024-11-09
  • 如何修复 PHP 中的“尝试获取非对象的属性”错误?
    如何修复 PHP 中的“尝试获取非对象的属性”错误?
    解决 PHP 中的“尝试获取非对象的属性”错误使用 PHP 时,您可能会遇到错误“尝试获取非对象的属性”获得非物体的财产。”当尝试访问尚未正确初始化或为 null 的对象的属性时,通常会发生此错误。在提供的代码的情况下,问题在于从数据库获取侧菜单数据。 mysql_fetch_object() 函数...
    编程 发布于2024-11-09
  • ## 如何修改 Python 源代码,同时保留格式和注释?
    ## 如何修改 Python 源代码,同时保留格式和注释?
    使用 AST 修改 Python 源代码解析、修改和写回 Python 源代码对于突变测试等任务来说是一项很有价值的任务。虽然标准 Python 模块提供了解析和编译代码的方法,但它们缺乏修改和重写源代码的能力。为了满足这一需求,一些库提供了解决方案:lib2to3: 由 Pythscope 和 2...
    编程 发布于2024-11-09
  • 如何修复 macOS 上 Django 中的“配置不正确:加载 MySQLdb 模块时出错”?
    如何修复 macOS 上 Django 中的“配置不正确:加载 MySQLdb 模块时出错”?
    MySQL配置不正确:相对路径的问题在Django中运行python manage.py runserver时,可能会遇到以下错误:ImproperlyConfigured: Error loading MySQLdb module: dlopen(/Library/Python/2.7/site-...
    编程 发布于2024-11-09
  • 如何使用 JavaScript 根据另一个下拉列表中的选择填充一个下拉列表?
    如何使用 JavaScript 根据另一个下拉列表中的选择填充一个下拉列表?
    使用 JavaScript 根据另一个下拉列表中的选择填充一个下拉列表当面临根据另一个下拉列表中的选择动态更新一个下拉列表中的选项的任务时,它是对于避免不必要的复杂性(例如数据库查询)至关重要。让我们探索一个简单的基于 JavaScript 的解决方案,无需 AJAX 调用即可完成此任务。为了说明此...
    编程 发布于2024-11-09
  • 如何从具有不同数组长度的字典创建 Pandas DataFrame?
    如何从具有不同数组长度的字典创建 Pandas DataFrame?
    从条目长度不均匀的字典创建 DataFrame在 Python 中,可以从每个条目保存一个 Numpy 数组的字典创建 DataFrame。然而,当条目之间的数组长度不同时,就会出现挑战。默认情况下,Pandas 需要统一长度的数组,从而导致类似“ValueError: arrays must al...
    编程 发布于2024-11-09
  • Bootstrap 4 Beta 中的列偏移发生了什么?
    Bootstrap 4 Beta 中的列偏移发生了什么?
    Bootstrap 4 Beta:列偏移的删除和恢复Bootstrap 4 在其 Beta 1 版本中引入了重大更改柱子偏移了。然而,随着 Beta 2 的后续发布,这些变化已经逆转。从 offset-md-* 到 ml-auto在 Bootstrap 4 Beta 1 中, offset-md-*...
    编程 发布于2024-11-09
  • 在 Go 中使用 WebSocket 进行实时通信
    在 Go 中使用 WebSocket 进行实时通信
    构建需要实时更新的应用程序(例如聊天应用程序、实时通知或协作工具)需要一种比传统 HTTP 更快、更具交互性的通信方法。这就是 WebSockets 发挥作用的地方!今天,我们将探讨如何在 Go 中使用 WebSocket,以便您可以向应用程序添加实时功能。 在这篇文章中,我们将介绍: WebSoc...
    编程 发布于2024-11-09
  • 为什么在 Java 中使用相同的种子时会得到相同的随机数?
    为什么在 Java 中使用相同的种子时会得到相同的随机数?
    具有固定种子的Java随机数:为什么输出相同?在您的代码中,您定义了一种使用以下命令生成随机数的方法指定的种子。但是,您会注意到,当您提供相同的种子时,所有 100 个生成的数字都是相同的。此行为是预期的,因为在 Random 构造函数中使用相同的种子会产生可预测的数字序列。种子是初始化随机数生成器...
    编程 发布于2024-11-09
  • jQuery Chaining 如何简化开发并提高代码效率?
    jQuery Chaining 如何简化开发并提高代码效率?
    理解 jQuery 中的对象和方法链接在 jQuery 中,链接允许在单个语句中串联多个 jQuery 方法。这使开发人员能够简化代码并轻松执行复杂的操作。链接的基本原理涉及每个 jQuery 方法的返回值。当调用 jQuery 方法时,它通常返回一个表示所选元素的 jQuery 对象。这允许在同一...
    编程 发布于2024-11-09

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3