C++信号量并发问题:启用计数退出逻辑后程序阻塞无输出
信号量顺序打印A/B/C时计数退出导致阻塞的原因分析
核心问题1:计数变量的非原子操作与内存可见性
你用的cnt如果是普通全局变量,++cnt不是原子操作,多个线程同时修改会导致计数混乱——比如实际已经累计到10,但因为线程间内存不可见,某个线程读不到最新值,会继续执行;或者计数被多线程交替修改,出现值跳变,导致退出逻辑失效。
更致命的是,一旦某个线程因为++cnt == 10触发退出,却没完成信号量的post操作,会直接打破信号量的同步链条:
- 比如常见的信号量设计是
semA初始为1,semB、semC初始为0。线程A拿semA打印后,post给semB;线程B拿semB打印后post给semC;线程C拿semC打印后post给semA,循环往复。 - 如果线程A在
++cnt == 10时直接跳出循环,没执行sem_post(semB),线程B会永远卡在sem_wait(semB),线程C也卡在sem_wait(semC),整个程序阻塞,且因为A没完成打印就退出,自然没有输出。
核心问题2:退出时机的逻辑错误
如果你的退出判断放在信号量wait操作之前,比如线程A先判断++cnt == 10,直接退出,连sem_wait(semA)都没执行,那semA的初始值1会一直被占用,其他线程根本没机会启动,直接全阻塞,完全没输出。
修复方向
- 把
cnt改成std::atomic<int>,保证计数操作的原子性和线程间的内存可见性。 - 调整退出逻辑:确保线程在退出前完成信号量的
post操作。比如,当cnt达到10时,线程完成当前打印和信号量释放后再退出,而不是中途打断。 - 或者由主线程控制循环次数,比如主线程循环10次,每次协调三个线程依次执行,线程本身只负责单次打印和信号量传递,避免线程自行判断退出的混乱。
内容的提问来源于stack exchange,提问作者Wang Tuma
相关产品推荐
相关产品推荐

