You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java闸门计数放行程序:如何实现排队顺序锁公平性?

闸门计数程序的公平性实现及Semaphore版本分析

一、改写Synchronized版本实现公平性

原代码使用的synchronized内置锁默认是非公平的,无法保证等待线程的获取顺序——对应业务场景就是先排队的人可能无法优先进入。要实现公平性,需要改用显式公平锁ReentrantLock(true),它会严格按照线程等待的FIFO顺序分配锁,从而保障排队人员的顺序公平性。

修正后的代码:

import java.util.concurrent.locks.ReentrantLock;

public class LineCount {
    private int totalInLine = 0;
    // 初始化公平锁,保证等待线程按先后顺序获取锁
    private final ReentrantLock fairLock = new ReentrantLock(true);

    public void addToLine() {
        fairLock.lock();
        try {
            totalInLine++;
            if (totalInLine == 5) {
                System.out.println("People may enter");
                totalInLine = 0;
            }
        } finally {
            fairLock.unlock();
        }
    }
}

二、现有Semaphore版本的问题及修正

你提供的Semaphore实现存在几个致命问题:

  1. 重新创建Semaphore导致线程永久阻塞:当执行semaphore = new Semaphore(5, true)时,已经调用acquire()但未完成操作的线程会持有旧的Semaphore实例,后续无法被唤醒,造成永久等待。
  2. availablePermits()判断非线程安全:多线程环境下,线程A调用acquire()后,线程B可能立刻也完成acquire(),此时线程A判断availablePermits() == 0的结果已经失效,会导致逻辑混乱(比如重复输出提示)。
  3. 冗余操作无意义:释放全部许可后重新创建Semaphore完全没必要,反而破坏了Semaphore的状态一致性。

修正后的Semaphore版本(兼顾公平性和业务逻辑):

import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;

public class LineCount {
    // 公平Semaphore,保证线程按排队顺序获取许可
    private final Semaphore semaphore = new Semaphore(5, true);
    // 原子计数器,安全统计排队人数
    private final AtomicInteger lineCount = new AtomicInteger(0);

    public void addToLine() throws InterruptedException {
        semaphore.acquire();
        try {
            int current = lineCount.incrementAndGet();
            if (current == 5) {
                System.out.println("People may enter");
                lineCount.set(0);
                // 释放所有许可,允许下一批5人排队
                semaphore.release(5);
            }
        } catch (Exception e) {
            // 异常时释放当前许可,避免许可泄漏
            semaphore.release();
            throw e;
        }
    }
}

修正逻辑说明:

  • 用AtomicInteger保证计数操作的原子性,避免多线程下的计数错误;
  • 公平Semaphore确保线程按FIFO顺序获取许可,对应业务场景中排队人员的先后顺序;
  • 不再重新创建Semaphore实例,维持Semaphore状态的一致性;
  • 增加异常处理,防止许可泄漏导致后续线程无法获取许可。

内容的提问来源于stack exchange,提问作者mattsmith5

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 07:43:24