C++20 std::atomic的notify触发其他原子变量wait返回问题咨询
问题现象解释
这个问题是GCC 11.1标准库实现和Linux futex机制共同作用的结果,核心原因有两个:
1. futex的哈希折叠导致跨变量唤醒
Linux上GCC的std::atomic wait/notify接口底层基于futex(快速用户空间互斥锁)机制实现。内核的futex等待队列并不会为每一个独立的原子变量地址分配单独的队列,而是会对地址做哈希折叠:地址相近、或者满足特定地址掩码规则的多个原子变量,会被映射到同一个futex等待队列。
你的两个全局std::atomic_flag变量condAtomicFlag1和condAtomicFlag2地址相邻,刚好被映射到了同一个futex等待队列。当你调用condAtomicFlag1.notify_one()时,内核会唤醒该队列上的所有等待线程,哪怕线程实际等待的是condAtomicFlag2。
2. GCC 11.1的实现bug导致不符合标准的虚假唤醒
按照C++20标准的要求,std::atomic::wait即使被虚假唤醒,也必须先重新检查原子变量的当前值:如果当前值仍然等于wait传入的old值,就必须回到阻塞状态,只有值发生变更时才会返回。
但你使用的GCC 11.1是首个支持C++20 atomic wait/notify的版本,存在已知的实现bug:std::atomic_flag::wait被唤醒后没有正确执行值校验步骤,直接返回,所以才会出现你观察到的、等待condAtomicFlag2的线程在值没有变更的情况下退出等待的问题。
解决方案
- 升级GCC到11.3及以上版本,该bug在后续版本中已经修复;
- 如果无法升级编译器,可以在wait返回后手动增加一次值校验,不满足条件就重新调用wait:
// 修改后的wait逻辑示例 while (condAtomicFlag2.test() == false) { condAtomicFlag2.wait(false); }
内容的提问来源于stack exchange,提问作者Elija
相关产品推荐
相关产品推荐

