C++20二进制信号量超出最大值仍可多次获取?求解释
C++20 std::binary_semaphore多次release后acquire不阻塞的原因解析
你的测试结果并非C标准规定的行为,这是**GCC 11版本中libstdc的实现bug**。
标准对binary_semaphore的明确要求
std::binary_semaphore是std::counting_semaphore<1>的类型别名,核心规则如下:
- 内部计数的上限为
max()返回的1,任何操作都不能让计数超过这个值。 - 调用
release()(无参数时等价于release(1))时,如果当前计数加1会超过上限,计数会被截断为上限值(即1),不会继续累加。
按照标准,你的测试代码应产生的行为:
- 初始化
sem为0,计数=0。 - 第一次
release():计数从0变为1(未超过上限)。 - 第二次
release():计数保持1(因加1会突破上限,被截断)。 - 第一次
acquire():计数从1变为0。 - 第二次
acquire():此时计数为0,调用会永久阻塞,程序无法正常返回。
测试结果异常的原因
GCC 11的libstdc++库对std::binary_semaphore的实现存在缺陷,未正确限制计数不超过max()值。多次调用release()会让计数突破上限(比如你的测试中计数被累加到了2),导致后续两次acquire()都能顺利递减计数,程序正常结束。
解决方式
该bug在GCC 12及以上版本的libstdc++中已被修复。你可以升级编译器到GCC 12或更高版本,重新编译运行代码,就能看到符合标准的阻塞行为。
内容的提问来源于stack exchange,提问作者DeZee
相关产品推荐
相关产品推荐

