MingW-w64中counting_semaphore引发死锁问题的技术问询
MingW-w64编译的C++计数信号量程序出现死锁,Linux/VS编译正常
问题现象
我编写的多线程程序,在Linux(g12.2.0、clang15.0.2-1)和Windows Visual Studio 2022 17.4.2环境下能稳定运行,但使用MingW-w64编译后频繁触发死锁——无论是否开启优化选项,通常循环不到10000次就会阻塞。
进一步调试发现,一段使用std::counting_semaphore的极简复现代码也存在相同问题。如果将acquire()替换为try_acquire_for(chrono::milliseconds(1000)),MingW-w64环境下程序就能永久运行无停顿。
复现代码
#include <iostream> #include <thread> #include <semaphore> using namespace std; std::counting_semaphore<3> cs1(0), cs2(0); int main(int argc, char const *argv[]) { thread th( []() { for (int j = 0;; j--) { cs1.release(); printf("%d\n", j); cs2.acquire(); } }); for (int i = 0;; i++) { cs2.release(); printf("%d\n", i); cs1.acquire(); } th.join(); return 0; }
死锁时的输出片段
... -804 805 806 -805 -806 -807 -808 807 808 809 810 -809 -810 -811 811 812 (blocked)
从输出可见,主线程执行print(i=812)前的cs2.release()操作,并未唤醒子线程中print(j=-811)后等待cs2.acquire()的逻辑。
MingW-w64环境信息
MingW-w64-g和MingW-w64-clang均存在此问题,使用的是winlibs个人构建版本,线程与异常模型为POSIX-seh:
winlibs personal build version gcc-12.2.0-llvm-14.0.6-mingw-w64ucrt-10.0.0-r2 This is the winlibs 64-bit standalone build of: - GCC 12.2.0 - GDB 12.1 - LLVM/Clang/LLD/LLDB 14.0.6 - MinGW-w64 10.0.0 (linked with ucrt) - GNU Binutils 2.39 - GNU Make 4.3 - PExports 0.47 - dos2unix 7.4.3 - Yasm 1.3.0 - NASM 2.15.05 - JWasm 2.12pre - ninja 1.11.0 - doxygen 1.9.5 This build was compiled with GCC 12.2.0 and packaged on 2022-08-28.
推测方向
目前无法确定问题根源:
- 代码逻辑在Linux和VS的标准库实现下能稳定运行,暂未发现明显线程不安全因素;
- 替换为带超时的
try_acquire_for后,MingW-w64环境下程序恢复正常,推测原始acquire的唤醒逻辑可能存在实现缺陷。
内容的提问来源于stack exchange,提问作者xxhxx
相关产品推荐
相关产品推荐

