信号量常被一句“做线程同步”带过,但面试官继续追问时会问:计数值代表什么?资源不可用时任务发生什么?为什么某些上下文不能用会睡眠的锁?这些问题本质上是在考并发模型。
可以把计数型Semaphore理解成“可用资源数量 + 等待队列”。获取操作尝试占用一个资源;没有资源时,调用者可能进入等待状态。释放操作归还资源,并可能唤醒等待者。

理解Semaphore要抓住四件事
计数值不是随便加减的变量
它应该对应可并发使用的资源数量或同步语义。初始化值为1时行为看起来像互斥,但Linux中做普通所有权互斥通常更倾向使用mutex。
down类操作可能阻塞
资源不可用时任务可能睡眠,所以不能在硬中断或不允许睡眠的原子上下文里随意使用。
up释放资源并唤醒等待者
释放路径需要和资源生命周期一致,避免重复释放、遗漏释放或在异常返回路径上泄漏。
spinlock和semaphore处理的等待方式不同
spinlock适合极短且不能睡眠的临界区;等待时间较长或需要调度的场景,应选择允许睡眠的同步原语。
参考回答
我会先看临界区所在的上下文以及等待期间能不能睡眠。如果是进程上下文、等待时间可能较长,并且同步对象适合睡眠等待,可以使用mutex或semaphore;如果是硬中断或原子上下文,就不能用会睡眠的锁。计数型semaphore更适合表示有限数量的可用资源,down获取、up释放,资源不足时调用者进入等待队列。若只是普通一对一互斥,我会优先考虑mutex并利用它更明确的所有权语义。
继续追问
为什么硬中断上下文不能调用可能睡眠的down操作?
binary semaphore和mutex看起来都只有0/1,为什么还要区分?
spinlock持有时间为什么要尽量短?
容易答错
回答“semaphore就是锁”,不解释计数和等待。
在任何上下文都认为可以使用同一种同步原语。
异常返回路径忘记释放资源,造成永久阻塞。

扫码关注






























