基于pthread_mutex_t、pthread_cond_t实现进程共享二元信号量的竞态问题咨询
结论
你的代码存在严重的竞态条件和多处未定义行为,无论启动顺序如何都无法稳定运行,具体问题和修复方案如下:
存在的问题
先启Pro2会直接报错退出
如果先启动Pro2,由于Pro2调用shm_open时没有传O_CREAT标志,此时共享内存还未被Pro1创建,Pro2会直接打印错误信息退出,根本无法进入后续逻辑。重复初始化同步对象触发未定义行为
POSIX标准明确规定:对已经完成初始化的pthread_mutex_t、pthread_cond_t对象再次调用pthread_mutex_init/pthread_cond_init,属于未定义行为。你现在两个进程都会执行共享内存中mutex和条件变量的初始化逻辑:
- 若Pro1还没初始化完同步对象,Pro2就已经启动并调用初始化函数,会导致同步对象状态损坏
- 若Pro1已经初始化完成,Pro2再调用初始化函数,同样会破坏已经正常可用的同步对象,后续锁操作、条件变量操作可能出现死锁、崩溃、逻辑错误等随机问题。
- 未初始化就调用mutex锁操作也是未定义行为
你在create_shm函数的create==true分支里,尝试对还未初始化的mutex调用pthread_mutex_lock修改flag,此时mutex是共享内存里的随机值,锁操作的行为完全没有任何保证。
修复方案
修改逻辑遵循核心规则:共享同步对象的初始化操作,只能由创建共享内存的进程执行一次
- 删掉Pro2代码中
pthread_mutex_init、pthread_cond_init的所有相关逻辑,Pro2映射共享内存后直接使用同步对象即可 - 把Pro1中mutex、条件变量的初始化逻辑,放到
create_shm调用之后、flag赋值之前,不需要对未初始化的mutex加锁,初始化完成后直接给flag赋值即可 - 如果你需要支持两个进程任意顺序启动,可以在共享内存结构里加一个原子类型的初始化完成标记,配合POSIX有名信号量保证只有第一个创建共享内存的进程执行初始化操作,其他进程阻塞等待初始化完成后再继续运行。
补充说明
你实现的post、wait操作逻辑本身是正确的,只要修复初始化逻辑,这个跨进程二元信号量就可以正常工作。
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

