2026年04月08日/ 浏览 13
正文:
在多线程编程中,控制线程的执行顺序是常见的需求。例如,需要线程A和线程B严格交替执行任务(如A→B→A→B)。Semaphore(信号量)作为Java并发包中的经典同步工具,通过许可证分配机制可实现这种精准控制。本文将揭示其实现原理,并提供可直接落地的代码方案。
Semaphore通过维护一组虚拟许可证控制资源访问:
– acquire():获取许可证(无可用时阻塞)
– release():释放许可证(唤醒等待线程)
通过初始化时分配不同数量的许可证,可控制线程的启动顺序,实现交替执行的核心在于:让两个线程互相等待对方的许可证释放。
假设线程A负责打印数字,线程B负责打印字母,需交替输出1→A→2→B→3→C...。解决方案如下:
1. 创建两个信号量:
– semaphoreA:初始1个许可证(允许线程A先执行)
– semaphoreB:初始0个许可证(阻塞线程B)
2. 线程A执行后释放semaphoreB的许可证
3. 线程B执行后释放semaphoreA的许可证
逻辑闭环:
线程A → 释放B的许可 → 线程B → 释放A的许可 → 线程A…
java
import java.util.concurrent.Semaphore;
public class AlternateExecution {
private static Semaphore semaphoreA = new Semaphore(1);
private static Semaphore semaphoreB = new Semaphore(0);
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
try {
for (int i = 1; i <= 3; i++) {
semaphoreA.acquire(); // 等待A的许可证
System.out.print(i + "→");
semaphoreB.release(); // 释放B的许可证
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
Thread threadB = new Thread(() -> {
try {
for (char c = 'A'; c <= 'C'; c++) {
semaphoreB.acquire(); // 等待B的许可证
System.out.print(c + "→");
semaphoreA.release(); // 释放A的许可证
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
threadA.start();
threadB.start();
}
}
输出结果:
1→A→2→B→3→C→
许可证初始化:
semaphoreA初始化为1,确保线程A首先获得执行权 semaphoreB初始化为0,使线程B在启动时立即阻塞 释放与获取的对称性:
semaphoreB.release()) semaphoreA.release()) 阻塞链的形成:
mermaid
graph LR
A[线程A] -->|释放B许可| B[线程B]
B -->|释放A许可| A
此模式适用于需严格交替执行的场景:
1. 生产者-消费者模型:单生产者与单消费者的精准协作
2. 多阶段任务处理:如阶段1→阶段2→阶段1的循环工作流
3. 双线程数据校验:线程A生成数据,线程B实时校验
acquire()和release()成对出现 InterruptedException中正确中断线程 通过Semaphore的许可证请求与释放机制,我们实现了线程间毫秒级的执行顺序控制。这种方案不仅代码简洁,且具备良好的扩展性。理解信号量的核心思想——“许可即权限”,能帮助开发者灵活解决更复杂的并发协作问题。