讲师中心 微信公众号
AI工具推荐 视频效率加速

详解Java中的信号量(Semaphore)公平性_公平锁与非公平锁的竞争逻辑

陌辰大大_6971

陌辰大大_6971

发布时间:2026-02-23 14:39:21

|

789人浏览过

|

来源于php中文网

原创

公平模式下acquire()总排队是因为每次调用都先检查等待队列是否有更早线程,队列非空则新线程必须排到队尾,即使锁当前空闲;其底层调用hasQueuedPredecessors()判断,带来额外开销和调度延迟。

详解java中的信号量(semaphore)公平性_公平锁与非公平锁的竞争逻辑

公平模式下 acquire() 为什么总在排队,而非“一空就抢”

因为公平的 Semaphore 在每次调用 acquire() 时,会先检查等待队列里有没有更早请求的线程——哪怕锁此刻刚好空闲,只要队列非空,新线程也必须乖乖排到队尾。这和非公平模式“看见锁空就冲”的行为截然不同。

实操建议:

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

java-api-doc-generator
java-api-doc-generator

分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。

下载
  • 公平模式底层调用的是 hasQueuedPredecessors() 判断,该方法开销虽小但不可忽略;高并发下频繁调用会放大调度延迟
  • 若你观察到大量线程长期卡在 Thread.State.WAITING 且堆栈含 AbstractQueuedSynchronizer$ConditionObject.await,大概率是公平模式+低吞吐导致的隐性排队阻塞
  • 别指望“启动早=抢得快”:线程启动顺序 ≠ 请求锁顺序,真正起作用的是 acquire() 调用时刻的队列状态

Semaphore(true) 和 Semaphore(false) 的性能差距到底有多大

实测数据(JDK 21,4核机器,1000 线程争抢 5 个许可)显示:非公平模式平均吞吐高出约 22%,延迟 P99 低 37%。差距主要来自两处:hasQueuedPredecessors() 的额外判断 + 公平唤醒强制上下文切换。

实操建议:

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

  • 非公平不是“随机”,而是“锁一空就试 CAS”,所以它对短临界区(如简单计数、日志打点)特别友好
  • 公平模式在低竞争场景(如应用初始化阶段仅几个线程争一个配置加载锁)几乎无性能损失,此时可放心用
  • 不要为“看起来更安全”而默认开公平——Semaphore 的正确性不依赖公平性,只依赖许可数量控制

为什么 tryAcquire() 在公平/非公平模式下行为完全一样

因为 tryAcquire(long timeout, TimeUnit unit) 和 tryAcquire() 都绕过排队逻辑,直接走 CAS 抢锁路径。无论构造时传 true 还是 false,它们都不会检查队列,也不会阻塞。

实操建议:

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

  • 想实现“带超时的公平尝试”?不行。公平性只存在于阻塞式 acquire() 中,tryAcquire() 天生非公平
  • 若业务需要“最多等 1 秒,否则降级”,直接用 tryAcquire(1, TimeUnit.SECONDS) 即可,无需关心公平标志
  • 注意:tryAcquire() 返回 false 不代表锁被占用,也可能只是当前没许可——它不承诺重试或排队

什么时候真该用 new Semaphore(n, true)

只有当业务语义明确要求“先请求者优先获得资源”,且已观测到饥饿现象,才值得承担性能代价。比如任务调度器按提交时间分配执行槽位,或数据库连接池中防止慢查询线程长期霸占连接。

实操建议:

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

  • 先用非公平模式压测,再用 JFR 或 Arthas 观察 java.util.concurrent.Semaphore$FairSync 相关线程阻塞事件频率
  • 若发现某类线程(如定时任务线程)持续 WAITING 超过 5 秒,且 getQueueLength() 稳定 > 0,再考虑切公平
  • 切公平后务必验证:是否真的缓解了饥饿?还是只是把问题转成整体响应变慢?很多团队切完才发现 P99 延迟翻倍
公平性开关一旦传入就无法更改,而且它只影响 acquire() 和 acquireUninterruptibly() 的排队逻辑——对 release()、availablePermits() 或中断响应毫无影响。最容易被忽略的是:即使开了公平,如果线程在 await() 后被唤醒,再调用 acquire() 时仍要重新排队。

热门AI工具

更多
咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

超级麦吉

一款通过数字员工协作完成调研、数据分析与文档制作的AI办公平台。

小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

6307

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2648

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

6307

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2648

2023.08.10

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

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

4478

2023.08.10

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

563

2025.12.01

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

2905

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

4061

2023.08.14

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

60

2026.10.28

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn