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

识别以下基于Monitor实现的Semaphore代码中的缺陷

自定义Semaphore实现的缺陷分析

先看给出的自定义信号量实现代码:

public class MySemaphore
{
    private object _mutex = new object();
    private int _currAvail;

    public MySemaphore(int capacity)
    {
        _currAvail​ = capacity;
    }

    public void Wait()
    {
        lock (_mutex)
        {
            if (_currAvail == 0) Monitor.Wait(_mutex);
            _currAvail--;
        }
    }

    public void Signal()
    {
        lock (_mutex) {
            _currAvail​++;
            Monitor.Pulse(_mutex);
        }
    }
}

核心缺陷

  • 虚假唤醒导致许可过度消耗:Wait方法中用if (_currAvail == 0)判断是否等待是错误的。Monitor.Wait可能被虚假唤醒(即使未调用Pulse/PulseAll,线程也可能被唤醒),或者当一个线程被Pulse唤醒后,另一个线程可能先获取锁并消耗了刚释放的许可,此时当前线程的_currAvail已回到0,但代码会直接执行_currAvail--,导致_currAvail变成负数,信号量许可被非法超额占用。正确做法是用while循环持续检查条件:

    while (_currAvail == 0) Monitor.Wait(_mutex);
    
  • 缺少参数合法性校验:构造函数未对capacity参数做校验,如果传入负数,_currAvail初始值为负,会导致Wait方法一开始就允许线程无限制消耗许可,完全违背信号量的设计意图。应该在构造函数中添加校验:

    if (capacity < 0) throw new ArgumentOutOfRangeException(nameof(capacity), "信号量容量不能为负数");
    _currAvail = capacity;
    

次要问题

  • Signal方法唤醒策略的局限性:Monitor.Pulse只会唤醒等待队列中的一个线程,这本身符合信号量释放一个许可的逻辑,但如果存在多个线程等待,Pulse的唤醒机制无法保证公平性(无法确保等待最久的线程被优先唤醒),不过这属于实现细节层面的问题,不影响核心功能的正确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 04:45:38